【问题标题】:Barriers and synchronization points with non-atomic variables - data race?非原子变量的障碍和同步点——数据竞争?
【发布时间】:2019-04-22 19:35:57
【问题描述】:

考虑以下程序:

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();
}

即使i 不是原子变量,该程序是否保证打印出2

根据cppreference

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

arrive_and_droparrive_and_wait 的调用绝不会引入彼此之间或彼此之间的数据竞争。

这表明每个arrive_and_wait 调用都有一个同步点。但是我不确定是否允许编译器重新排序i 上的读/写操作,因为它是非原子的。

【问题讨论】:

  • Bartop 是对的。“对arrive_and_wait() 的调用与调用的返回同步”。这就是你的答案.. 如果 A 与 B 同步,则在 A (i = 2) 头间排序之前的语句发生在 B (cout &lt;&lt; i) 之后排序的语句之前。这些陈述是否是原子的无关紧要;这与互斥锁用于在线程之间同步非原子数据的机制完全相同。

标签: c++ multithreading concurrency language-lawyer barrier


【解决方案1】:

根据我对std::barrier reference(我的重点)的理解:

屏障有一个完成阶段,一旦参与线程集中的所有线程到达同步点,其中一个参与线程就会执行该完成阶段。到达和等待和到达和丢弃调用与完成阶段的开始同步; t完成阶段的结束与所有被其完成阻塞的调用的返回同步

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

在线程之间,如果以下任何一项为真,则评估 A 线程间发生在评估 B 之前

1) A 与 B 同步

2) A 在 B 之前是依赖排序的

3) A 与某些评估 X 同步,并且 X 在 B 之前排序

4) A 在某个评估 X 之前被排序,并且 X 线程间发生在 B 之前

5) 线程间发生在某个评估 X 之前,并且 X 线程间发生在 B 之前

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    相关资源
    最近更新 更多