【发布时间】:2013-03-09 11:22:09
【问题描述】:
我试图准确了解如何使用原子操作安全地管理共享指针。原来 VC11 (Visual Studio 2012) 支持 C++11,因此可以允许 std::shared_ptr 上的读/写竞争。 我想检查我是否理解了基础知识,然后询问有关 VC11 中 std::shared_ptr 上原子操作的实现细节。
std::shared_ptr<A> x, y, z;
x = std::make_shared<A>(args1);
y = std::make_shared<A>(args2);
线程 1
std::shared_ptr<A> temp = std::atomic_load(y);
线程 2
std::atomic_store(&y, z);
如果没有原子,竞争可能会导致temp 最终处于损坏状态,或者线程 2 可能会删除原始 y 指向的 A 实例,就像线程 1 试图复制和添加 shared_ptr 一样,这会让它指向一个“僵尸”对象。
关于 VC11 中 atomic_load 和 atomic_store 的问题:
我注意到他们使用自旋锁对全局变量执行测试和设置。 所以我想知道:为什么不在 shared_ptr 本身的引用计数器的最高位上进行测试和设置呢?这样不同shared_ptr上的锁就不会相互竞争。没有这样做是有原因的吗?
编辑:atomic_is_lock_free 的 VS 实现。不足为奇,因为它对一切都使用自旋锁。仍然想知道为什么他们不能让它使用 shared_ptr-instance-specific 锁而不是全局锁。
template <class _Ty> inline
bool atomic_is_lock_free(const shared_ptr<_Ty> *)
{ // return true if atomic operations on shared_ptr<_Ty> are lock-free
return (false);
}
【问题讨论】:
-
您是否检查过 std::atomic_is_lock_free(&some_shared_ptr) 在您的平台上是否为真。
-
我在某处读到
shared_ptr在内部使用原子操作。也许您不需要将它们混合在一起。我说的对吗? -
shared_ptr 使用原子操作来增加和减少其使用计数。如果没有这些原子操作,即使读取/读取竞争(即 2 个线程从同一个 shared_ptr 分配到一个本地线程),引用计数器的值也可能无效 - 如果不是,在某些排序下使用计数可能会增加不到 2原子更新。但仅此一项并不能解决我在帖子中提到的 2 个竞争条件;这是一个单独的问题。
标签: c++ visual-studio-2012 shared-ptr atomic