任何方式实现对值的多线程访问,而无需读者锁定

时间:2013-03-09 00:43:10

标签: c++ c++11 synchronization thread-safety smart-pointers

我正在尝试实现一种简约同步机制,其中一个对象包含某些类型为Foo的值,此Foo可能是一个重量级类型,但很少更改其值。可以从多个线程访问该对象,几乎100%读取。

我试图想出一种方法来使这项工作没有对读者的任何锁定要求。我的第一次尝试是让我的类通过Foo类型的共享指针成员包含std::shared_ptr<Foo>。 读取操作只是复制构造共享指针,取消引用它,然后使用该值的“版本”来做任何他们想做的事。

写操作应该将他们的更改应用到Foo的新副本中,一旦完成,尝试用新的Foo替换当前版本的shared_ptr<Foo>

我意识到这对于boost::intrusive_ptr<Foo>是不可能的,因为复制构造函数可能会在尝试更新它的情况下进入读/写竞争,并读取损坏的值。 我可以使用带有原子计数器的intrusive_ptr_add_ref并使用CAS操作进行版本更新来解决这个问题,但是仍然存在一种我无法摆脱的竞争条件:读者可以在调用之前暂停{{ 1}}在一个即将被另一个将计数降低到0的线程销毁的实例上。

这种方法似乎从根本上破坏了某些东西。

有没有办法实现这一点,不依赖于关键部分,读者/作者锁定或完整的RCU(读取 - 复制 - 更新)?也许我错过了一些简单的事情。 平台是Win7 + / x86 / x64。

2 个答案:

答案 0 :(得分:4)

解决方案是首先使用具有新std::shared_ptr<Foo>的本地Foo,并通过atomic assignment方法将其分配给全局std::shared_ptr。澄清:不要使用普通作业。从链接中,您可以使用:

atomic_store( &global_ptr, std::make_shared<Foo>(...) );

答案 1 :(得分:0)

这会有效..

Foo * globalFoo;
.
.

Foo* newFoo = new Foo();
Foo* temp;
do {
    temp = globalFoo;
} while(! std::atomic_compare_exchange_weak(temp, globalFoo, newFoo));