内存同步,从不同线程调用回调

Memory Synchronization with callback called from a different thread

提问人:Nieta 提问时间:11/12/2023 最后编辑:Nieta 更新时间:11/12/2023 访问量:116

问:

这是我上一个问题的后续问题

我有两个线程,我希望使用原子进行同步,并且使用最宽松的内存顺序......

//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 创建/捕获同步,就像线程一样,但找不到任何同步。releaseacquirejoin()

问题:

  1. 代码是否足以满足上述要求?从 C++ 内存模型的角度来看,#2 中的似乎是不够的,因为它是在与设置不同的线程上执行的,根据常识,我假设通过捕获 lambda 还将看到对象的更新状态,包括存储在 #4 上,即使它在不同的线程上被调用, 因此,线程 3 上的更改将通过传递性对线程 2 可见......(但是如果我只捕捉呢?releasecounterthiscounterreleasecounterblocked

  2. 如果上述问题的答案是“否”,我是否可以使用如上所述的单个原子变量来完成这项工作,而无需使用互斥锁锁定该部分? (例如,我想过通过放在第 #3 行来创建一个“假”序列,但这似乎......丑?骇人听闻?额外的商店只是为了防止重新订购)acquirereleaseblocked.store(true, std::memory_order::release);

  3. 如果是,答案如何变化?例如,我可以(即),这似乎已经足够了。在这种情况下,还将阻止将 w.r.t 重新排序到 ?counterstd::atomic<int>counter.fetch_add(1)seq_cstcounter.fetch_add(1, std::memory_order_acq_rel)load

C++ 多线程原子 内存屏障 stdatomic

评论

1赞 HolyBlackCat 11/12/2023
这取决于工作方式。如果里面有,并且调用回调的线程执行,那么你就没问题了。set_callbackreleaseacquire
0赞 Nieta 11/12/2023
我看不出回调线程上的内容如何更改任何内容,因为它不会与线程 1 上的任何内容同步。acquirerelease
0赞 Red.Wave 11/12/2023
你有一个复制粘贴的错别字:似乎是意思.如果代码段中有这样的错别字,你会得到令人困惑的评论。我想你应该仔细阅读和编辑你的问题。disabledblockedmemory_order
0赞 Nieta 11/12/2023
@Red.Wave 确实,谢谢。不过,内存顺序是按预期进行的......
1赞 Peter Cordes 11/13/2023
与围栏不同,释放操作只有单向排序。preshing.com/20131125/......就像我说的,在 x86 上编译为零 asm 指令,只阻止编译时重新排序。在实践中,如果函数调用没有内联,这已经不会发生。(它不能,因为你说库是纯二进制的,所以你不能改进它。atomic_thread_fence(memory_order_release)

答: 暂无答案