非原子变量的障碍和同步点——数据竞争?

Posted

技术标签:

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

考虑以下程序:

int                        i0;
std::experimental::barrier b2;

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) 之后排序的语句之前。这些陈述是否是原子的无关紧要;这与互斥锁用于在线程之间同步非原子数据的机制完全相同。 【参考方案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 之前

【讨论】:

以上是关于非原子变量的障碍和同步点——数据竞争?的主要内容,如果未能解决你的问题,请参考以下文章

java并发编程原子变量和非阻塞的同步机制

原子线程围栏:为什么在这个非原子变量上存在数据竞争?这有关系吗?

标准原子同步和非原子变量:不是过时的数据?

java并发编程11.原子变量与非阻塞同步机制

第十五章 原子变量和非阻塞同步机制

Java并发编程实战 第15章 原子变量和非阻塞同步机制