这里有原子新手。我的代码当前看起来像这样(简化):
std::atomic<Object*> object;
void thread_a()
{
object.load()->doSomething(); // (1)
}
void thread_b()
{
Object* oldObject = object.load();
Object* newObject = new Object();
// Update new object accordingly...
while (!object.compare_exchange_weak(oldObject, newObject));
delete oldObject;
}
换句话说,我的想法是让thread_b
原子交换共享对象(双缓冲),而thread_a
对其执行一些工作。我的问题:我可以安全地假设在thread_a
对其上调用doSomething()
时,共享对象将被“保护”以防止数据争用吗,如(1)所述吗?
答案 0 :(得分:8)
使用load()
获取指针是原子的,但是对doSomething()
本身的调用不是原子的。
这意味着可以在调用load()
之后但在调用doSomething()
之前交换指针(这意味着在错误且现在已删除的对象上调用doSomething()
)。
也许互斥锁可能是一个更好的选择?
答案 1 :(得分:3)
我经常这样做,但是...使用共享指针,并且它是无锁的!
正如某些程序员Dude在回答中所建议的那样,您的设计存在问题。但是,如果您使用shared_ptr
进行此操作,并且您的程序逻辑允许这样做,那么您会没事的。
与shared_ptr
一起使用的原因是,只要您的对象位于其他地方,就不会强行删除它。因此,这是您的操作方式:
std::shared_ptr<Object> object;
void thread_a()
{
std::atomic_load(&object)->doSomething(); // (1)
}
void thread_b()
{
std::shared_ptr<Object> oldObject = std::atomic_load(&object);
std::shared_ptr<Object> newObject = std::make_shared<Object>();
// Update new object accordingly...
while (!std::atomic_compare_exchange_weak(object, oldObject, newObject));
}
编辑:此atomic_load
专用于shared_ptr
。这似乎引起了评论的混乱:https://en.cppreference.com/w/cpp/memory/shared_ptr/atomic