如何使用原子指针执行双缓冲

How to perform double buffering with atomic pointers?

本文关键字:执行 缓冲 指针 何使用      更新时间:2023-10-16

这里是原子新手。我的代码目前看起来是这样的(简化(:

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()时,我能安全地假设共享对象将受到"保护"以防数据争用吗?

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