我正在尝试实现一种简约同步机制,其中一个对象包含某些类型为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。
答案 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));