MST

星途 面试题库

面试题:C++返回常量引用在多线程环境下的挑战

假设在多线程环境下,有一个函数返回常量引用指向共享资源。请分析可能会出现哪些线程安全问题?如何在不改变函数返回类型为常量引用的前提下,保证线程安全?请提供详细的分析过程和代码解决方案。
20.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

可能出现的线程安全问题

  1. 数据竞争:多个线程同时访问共享资源,由于没有同步机制,可能导致一个线程读取到正在被另一个线程修改的数据,从而得到不一致或错误的结果。例如,一个线程正在更新共享资源,而另一个线程同时读取这个资源,读取到的可能是部分更新的数据。
  2. 悬空引用:如果共享资源在某个线程中被释放,而其他线程仍然持有指向该资源的常量引用,那么这些引用就会变成悬空引用,访问悬空引用会导致未定义行为。

保证线程安全的分析与解决方案

  1. 使用互斥锁(Mutex)
    • 分析:互斥锁可以保证在同一时间只有一个线程能够访问共享资源。当一个线程获取到互斥锁时,其他线程必须等待,直到该线程释放互斥锁。
    • 代码示例(C++)
#include <iostream>
#include <mutex>
#include <thread>

class SharedResource {
public:
    int data;
    SharedResource(int value) : data(value) {}
};

std::mutex resourceMutex;
SharedResource* sharedResourcePtr = new SharedResource(0);

const SharedResource& getSharedResource() {
    std::lock_guard<std::mutex> lock(resourceMutex);
    return *sharedResourcePtr;
}

void threadFunction() {
    const SharedResource& resource = getSharedResource();
    std::cout << "Thread read data: " << resource.data << std::endl;
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(threadFunction);
    }

    for (auto& thread : threads) {
        thread.join();
    }

    delete sharedResourcePtr;
    return 0;
}
  1. 使用读写锁(Read - Write Lock)
    • 分析:读写锁允许多个线程同时进行读操作,但只允许一个线程进行写操作。当有写操作时,所有读操作和其他写操作都必须等待。这样可以提高读操作的并发性能,同时保证写操作的原子性。
    • 代码示例(C++,使用 std::shared_mutex
#include <iostream>
#include <shared_mutex>
#include <thread>

class SharedResource {
public:
    int data;
    SharedResource(int value) : data(value) {}
};

std::shared_mutex resourceMutex;
SharedResource* sharedResourcePtr = new SharedResource(0);

const SharedResource& getSharedResource() {
    std::shared_lock<std::shared_mutex> lock(resourceMutex);
    return *sharedResourcePtr;
}

void readThreadFunction() {
    const SharedResource& resource = getSharedResource();
    std::cout << "Read Thread read data: " << resource.data << std::endl;
}

void writeThreadFunction() {
    std::unique_lock<std::shared_mutex> lock(resourceMutex);
    sharedResourcePtr->data++;
    std::cout << "Write Thread updated data" << std::endl;
}

int main() {
    std::thread readThreads[10];
    std::thread writeThread(writeThreadFunction);

    for (int i = 0; i < 10; ++i) {
        readThreads[i] = std::thread(readThreadFunction);
    }

    for (auto& thread : readThreads) {
        thread.join();
    }
    writeThread.join();

    delete sharedResourcePtr;
    return 0;
}