使用限制
- 对象可能已销毁:
std::weak_ptr
不增加对象引用计数,在多线程环境下,当通过 lock
方法尝试获取 std::shared_ptr
时,对象可能在其他线程已经被销毁,导致获取到空指针。
- 线程安全问题:
std::weak_ptr
本身的操作并非线程安全。例如,在一个线程中检查 weak_ptr
是否过期,同时另一个线程销毁了对象,可能会出现不一致的结果。
代码示例
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
std::mutex weakPtrMutex;
std::weak_ptr<int> weakObj;
void createObject() {
std::shared_ptr<int> sharedObj = std::make_shared<int>(42);
std::lock_guard<std::mutex> lock(weakPtrMutex);
weakObj = sharedObj;
}
void accessObject() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::shared_ptr<int> sharedObj;
{
std::lock_guard<std::mutex> lock(weakPtrMutex);
sharedObj = weakObj.lock();
}
if (sharedObj) {
std::cout << "Accessed object: " << *sharedObj << std::endl;
} else {
std::cout << "Object has been destroyed." << std::endl;
}
}
int main() {
std::thread t1(createObject);
std::thread t2(accessObject);
t1.join();
t2.join();
return 0;
}
竞争条件及解决方法
- 竞争条件:在多线程环境下,可能出现一个线程在检查
weak_ptr
是否过期后,还未获取 shared_ptr
时,对象在其他线程被销毁。
- 解决方法:
- 使用互斥锁,如上述代码中通过
std::mutex
来保护对 weak_ptr
的操作,确保在同一时间只有一个线程能访问和修改 weak_ptr
。这样可以避免多个线程同时操作 weak_ptr
导致的不一致问题。
- 当获取
shared_ptr
后,及时检查其是否为空,防止对已销毁对象的悬空引用。