rsj*_*ffe 1 c++ multithreading weak-ptr c++20
下面是一些显示我的用例的示例代码.我有一个PIMPL,可以共享实现(它只是一堆昂贵的数据),但实现可以在不再需要时销毁.类的一个实例HasImpl使用一个共享指针Impl,类定义包括一个static weak_ptrto Impl作为新指针的"指针分配器" HasImpl,给它们一个句柄来处理Impl已经存在的句子.
该示例有两个用于调用的替代方案 - weak_ptr::lock假设下面问题1-3的答案都是"是",而另一个则没有.我喜欢的唯一原因weak_ptr::lock是线程安全的,有可能是多个线程试图让指针的副本Impl,如果lock是线程安全的,执行的大多数线程不会有通过一个静态变量的定义(线程必须检查它是否已经初始化)并且不必竞争获取互斥锁.
/* In HasImpl.h */
class HasImpl {
public:
HasImpl();
private:
class Impl;
static std::weak_ptr<Impl> sharedImplDispenser;
std::shared_ptr<Impl> myPtrToSharedImpl;
}
/* In HasImpl.cpp */
class HasImpl::Impl {
public:
Impl(); //constructor that takes a lot of time to run
//Lots of stuff, expensively produced, accessable to HasImpl through a shared_ptr to Impl
}
/* hypothetical constructor if weak_ptr::lock is thread-safe */
HasImpl::HasImpl() : myPtrToSharedImpl{sharedImplDispenser.lock()}
{
if (!myPtrToSharedImpl) {
static std::mutex mtx;
std::lockguard<std::mutex> lck(mtx);
myPtrToSharedImpl = sharedImplDispenser.lock();
if (!myPtrToSharedImpl) {
const auto new_impl{std::make_shared<Impl()};
sharedImplDispenser = new_impl; // the only place in the program where a value is assigned to sharedImplDispenser
myPtrToSharedImpl = new_impl;
}
}
}
/* hypothetical constructor if weak_ptr::lock is not thread-safe */
HasImpl::HasImpl()
{
static std::mutex mtx;
std::lockguard<std::mutex> lck(mtx);
myPtrToSharedImpl = sharedImpl.lock();
if (!myPtrToSharedImpl) {
const auto new_impl{std::make_shared<Impl()};
sharedImplDispenser = new_impl; // the only place in the program where a value is assigned to sharedImplDispenser
myPtrToSharedImpl = new_impl;
}
}
Run Code Online (Sandbox Code Playgroud)
std::weak_ptr不是空的并且在遥远的过去某个时间被分配了一个指针,如果一个线程调用weak_ptr::lock而另一个线程可能正在调用,那么控制块是否正常weak_ptr::lock?weak_ptr::lock而另一个线程可能正在将一个ptr分配给空的weak_ptr足够安全吗?也就是说,该值是返回nullptr还是新指针?我不在乎nullptr是否是假的(也就是说,已经发生了这种分配但其他线程还不知道它).我只是不想破坏控制块或从调用中获取无效的指针值.weak_ptr::lock对象的最后一个shared_ptr被破坏线程安全吗?std::atomic<std::weak_ptr<T>>C++ 20会解决这个问题吗?该标准明确表示weak_ptr::lock"以原子方式执行".所以答案1和3.
#2,如果你问有关分配到相同的 weak_ptr,那么它是一个数据的比赛.改变共享状态的use_count操作不会引发数据争用,但复制或操纵weak_ptr本身不仅仅是在捅东西use_count.
但是,如果你正在谈论锁定一个weak_ptr同时将另一个同时weak_ptr处理同一共享状态的另一个解锁,那就没问题.这两个只通过共享状态的计数进行交互,这被认为是好的.
是的,atomic<weak_ptr<T>>允许您从多个线程操纵同一个对象.