如何使用原子指针执行双缓冲?
How to perform double buffering with atomic pointers?
这里是 Atomic 新手。我的代码目前看起来像这样(简化):
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
对其执行一些工作。我的问题:我是否可以安全地假设共享对象将 "protected" 对抗数据竞争,而 thread_a
对其调用 doSomething()
,如 (1) 中所做的那样?
使用 load()
获取指针将是原子的,但对 doSomething()
本身的调用将不是原子的。
这意味着可以在调用 load()
之后但在调用 doSomething()
之前交换指针(这意味着 doSomething()
在错误的对象上调用,现在已删除)。
也许在这里互斥锁是更好的选择?
我经常这样做,但是...使用共享指针,而且它是无锁的!
您的设计存在问题,正如某些程序员老兄在他的回答中所建议的那样。但是,如果您使用 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
这里是 Atomic 新手。我的代码目前看起来像这样(简化):
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
对其执行一些工作。我的问题:我是否可以安全地假设共享对象将 "protected" 对抗数据竞争,而 thread_a
对其调用 doSomething()
,如 (1) 中所做的那样?
使用 load()
获取指针将是原子的,但对 doSomething()
本身的调用将不是原子的。
这意味着可以在调用 load()
之后但在调用 doSomething()
之前交换指针(这意味着 doSomething()
在错误的对象上调用,现在已删除)。
也许在这里互斥锁是更好的选择?
我经常这样做,但是...使用共享指针,而且它是无锁的!
您的设计存在问题,正如某些程序员老兄在他的回答中所建议的那样。但是,如果您使用 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