代码之家  ›  专栏  ›  技术社区  ›  Vittorio Romeo

具有非原子变量的障碍和同步点-数据竞赛?

  •  6
  • Vittorio Romeo  · 技术社区  · 6 年前

    考虑以下程序:

    int                        i{0};
    std::experimental::barrier b{2};
    
    int main()
    {
        std::thread t0{[] {
            b.arrive_and_wait();
            std::cout << i << '\n';
        }};
    
        std::thread t1{[] {
            i = 2;
            b.arrive_and_wait();
        }};
    
        t0.join();
        t1.join();
    }
    

    这个节目保证打印出来吗 2 即使 i 不是原子变量吗?

    根据 cppreference :

    呼吁 arrive_and_wait 与屏障完成阶段的开始同步。完成阶段的完成与来自调用的返回同步。

    呼吁 arrive_and_drop 到了,等等 不要与自己或彼此介绍数据竞争。

    这表明在每个节点上都有一个同步点 到了,等等 打电话。但是,我不确定是否允许编译器对上的读/写操作重新排序 因为它是非原子的。

    1 回复  |  直到 6 年前
        1
  •  3
  •   bartop    6 年前

    从我所理解的 std::barrier reference (我强调):

    屏障有一个完成阶段,当一组参与线程中的所有线程到达同步点时,由其中一个参与线程执行。到达-等待和到达-丢弃呼叫与完成阶段的开始同步;t 完成阶段的结束与完成阻止的所有呼叫的返回同步。 .

    您可以假设在不同线程中的屏障之前所做的所有更改在其他线程中都是可见的,即使它们不是原子的。AS this reference 指出(我的重点):

    在线程之间,如果下面的任何一个为真,则在计算B之前计算A线程间

    1)A与B同步

    2)a是在b之前订购的依赖项

    3)a与某个评价x同步,x在b前排序

    4)A在某个评价X之前排序,X在B之前发生线程间排序。

    5)一个线程间发生在某个计算x之前,而x个线程间发生在b之前。