提问人:Nieta 提问时间:11/12/2023 最后编辑:Nieta 更新时间:11/12/2023 访问量:116
内存同步,从不同线程调用回调
Memory Synchronization with callback called from a different thread
问:
这是我上一个问题的后续问题
我有两个线程,我希望使用原子进行同步,并且使用最宽松的内存顺序......
//class members
std::atomic_bool blocked = true;
int counter = 0; //in practice - std::atomic<int>
[Thread 1]
while (...)
{
counter++; //#4
if (blocked.load(std::memory_order::acquire))
{
// #3
//Do stuff
event.set_callback([this]() //#1
{
//Executed on another thread
blocked.store(false, std::memory_order::release); //#2
blocked.notify_one();
});
}
}
[Thread 2]
while (...)
{
blocked.wait(true, std::memory_order::acquire);
if (counter > ...)
{
}
blocked.store(true, std::memory_order::release);
}
#1 中的回调稍后将由外部事件触发,并在另一个线程上执行。
我想确保线程 2 看到线程 1 中设置的计数器
的正确值。
我已经搜索了类似的问题,也在标准中搜索,看看是否有隐式的 lambda 创建/捕获同步,就像线程一样,但找不到任何同步。release
acquire
join()
问题:
代码是否足以满足上述要求?从 C++ 内存模型的角度来看,#2 中的似乎是不够的,因为它是在与设置不同的线程上执行的,但根据常识,我假设通过捕获 lambda 还将看到对象的更新状态,包括存储在 #4 上,即使它在不同的线程上被调用, 因此,线程 3 上的更改将通过传递性对线程 2 可见......(但是如果我只捕捉呢?
release
counter
this
counter
release
counter
blocked
如果上述问题的答案是“否”,我是否可以使用如上所述的单个原子变量来完成这项工作,而无需使用互斥锁锁定该部分? (例如,我想过通过放在第 #3 行来创建一个“假”序列,但这似乎......丑?骇人听闻?额外的商店只是为了防止重新订购)
acquire
release
blocked.store(true, std::memory_order::release);
如果是,答案如何变化?例如,我可以(即),这似乎已经足够了。在这种情况下,还将阻止将 w.r.t 重新排序到 ?
counter
std::atomic<int>
counter.fetch_add(1)
seq_cst
counter.fetch_add(1, std::memory_order_acq_rel)
load
答: 暂无答案
评论
set_callback
release
acquire
acquire
release
disabled
blocked
memory_order
atomic_thread_fence(memory_order_release)