面试题答案
一键面试1. std::weak_ptr过期检查在多线程环境中可能面临的问题
- 竞争条件:在多线程环境下,一个线程在检查
std::weak_ptr
是否过期后,在尝试获取std::shared_ptr
之前,另一个线程可能已经释放了对应的资源,导致获取到的std::shared_ptr
为空指针(空悬指针问题)。
2. 设计多线程安全机制的关键思路
- 使用互斥锁:通过互斥锁(如
std::mutex
)来保护std::weak_ptr
的检查和获取操作,确保同一时间只有一个线程能够进行这些操作。 - 双重检查锁定:在获取锁之前先进行一次快速的过期检查,减少不必要的锁竞争。
3. 代码框架示例
#include <memory>
#include <mutex>
#include <iostream>
#include <thread>
class Data {
public:
Data(int value) : data(value) {}
int data;
};
std::weak_ptr<Data> weakPtr;
std::mutex weakPtrMutex;
std::shared_ptr<Data> getSharedPtrSafely() {
// 快速检查,减少锁竞争
if (auto shared = weakPtr.lock()) {
return shared;
}
std::unique_lock<std::mutex> lock(weakPtrMutex);
// 再次检查,因为在获取锁的过程中可能资源已释放
if (auto shared = weakPtr.lock()) {
return shared;
}
return nullptr;
}
void threadFunction() {
auto shared = getSharedPtrSafely();
if (shared) {
std::cout << "Thread accessed data: " << shared->data << std::endl;
} else {
std::cout << "Thread: Data has expired." << std::endl;
}
}
int main() {
auto sharedPtr = std::make_shared<Data>(42);
weakPtr = sharedPtr;
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
// 模拟资源释放
sharedPtr.reset();
std::thread t3(threadFunction);
std::thread t4(threadFunction);
t3.join();
t4.join();
return 0;
}
在上述代码中:
weakPtrMutex
用于保护weakPtr
的操作。getSharedPtrSafely
函数通过双重检查锁定机制,先快速检查weakPtr
是否过期,然后获取锁再次检查并尝试获取std::shared_ptr
,确保多线程环境下安全地检查和获取资源。