【发布时间】:2021-07-28 10:19:06
【问题描述】:
当你有一个weak_ptr,你做到了:
std::weak_ptr<int> wp; // Pretend it's assigned to a shared_ptr
if (!wp.expired()) // Equivalent to use_count() != 0
{ /* Here we're not 100% sure the raw pointer is accessible because a shared_ptr from another thread
could have been destroyed, and is in the process of decrementing the use_count from 1 to 0 and calling the deleter.*/
}
另一方面:
std::weak_ptr<int> wp; // Pretend it's assigned to a shared_ptr
if (wp.expired()) Equivalent to use_count() == 0
{ /* Here we are sure that the raw pointer is invalid because of the interesting property that once the use_count is 0 it can't get incremented anymore */
}
如果资源仍然有效,访问指针的正确方法是调用 lock,如果资源有效,它将向资源返回一个 shared_ptr,如果资源无效,则返回一个空/null shared_ptr:
if (std::shared_ptr shp = wp.lock())
{// We know the resource is valid, we can use it
}
我不明白的是,根据文档,锁定功能被定义为:
有效地返回
expired() ? shared_ptr<T>() : shared_ptr<T>(*this),以原子方式执行。
所以如果expired()(相当于use_count() == 0)返回true,那么我们确定指针不能被取消引用,我们得到一个空的shared_ptr。另一方面,如果 expired() 返回 false 我们会返回一个 shared_ptr 到资源,但问题是,正如我上面提到的,当 expired() 返回 true 我们知道指针是错误的,但是当它返回 false 时可能是假阴性,但我们会返回一个 shared_ptr。当我们检查返回的 shared_ptr 时,另一个线程可能仍在写入控制块的过程中,对吧?
当文档说“以原子方式执行”时,这是否意味着每次您想访问weak_ptr 时调用lock() 方法都使用互斥锁,还是使用原子操作?如果是这样,这样做的性能成本是多少?
我不认为它对计数器使用原子类型,因为我听说过一种经常实现的技巧,我认为这是一种避免使用原子类型/操作的方法:
为所有 shared_ptr 实例添加一个只是一种优化(保存 复制/分配 shared_ptr 时一个原子增量/减量 实例)Link。
【问题讨论】:
-
老实说,我看不出
weak_ptr::expired()有什么好处。在多线程环境中,通过shared_ptr的最终强引用可以在另一个线程上释放,如果expired()返回true,则您明确知道该对象已被删除,但如果它返回false,则表示“活跃度”对象的有效期不再超过此时间。在您致电lock()之前,您无法安全地假设任何事情 -
根据cppreference.com 上的文档:
This function is inherently racy if the managed object is shared among threads. In particular, a false result may become stale before it can be used. A true result is reliable。 -
最后的评论。我认为
expired是 Boost 的保留,它明确建议底层use_count函数是“仅用于调试和测试目的,而不是用于生产代码。”。 -
@selbie 所以每次你想访问weak_ptr资源时都必须使用原子操作?这就是lock()发生的事情吗?还是互斥锁?我什至不知道有什么区别。
-
@Zebrafish:“必要”或“不必要”是fluid。此外,尚不清楚您的问题实际上是什么。您的问题似乎不是原子操作实际上是否是原子的,而是更普遍地不相信 C++ 标准库会对这种类型有任何线程保护。 “它使用 std::atomic 还是 std::mutex?” 这是一个实现细节。操作是原子的;如何实现这不是你的事。
标签: c++ smart-pointers weak-ptr