同步 (SW) 顺序与同步顺序 (SO)

Synchronization-with (SW) order vs synchronization order (SO)

此处:http://cs.oswego.edu/pipermail/concurrency-interest/2013-November/011954.html 其中一位对话者说:

In your reasoning, you do not distinguish between synchronization order (so) and synchronizes-with order (sw)

我也看不出 so 和 sw 之间的区别。有人可以解释一下吗?


EDITED_1:

   read(a, !null) (1)
      \--po--> vread(a.f, 0)
                    \---so---> vstore(a.f, 42)
                                    \---po---> store(a) (4)

特别是,我不理解上图:read(a, !null)(1) 表示操作读取 a 并且它是 not-null 而作为一个动作 (4) store(a) 存储到 a 变量 after (1)。

所以,如果我们有:

read(a) --> store_to_a read(a) 怎么 return 不为空?


EDITED_2 我不明白:

   vstore(A.f, null) --so--> vread(A.f, null) --so--> vstore(A.f, 42)

什么意思vstore(A.f, null)。我的意思是 A.fint。那么,为什么作者将null存储为int呢?与 vread(A.f, null)

相同

同步顺序是每个单独执行的 属性,它是该执行的 所有 同步操作的顺序。

Synchronizes-with 是部分基于同步顺序的关系(参见 JLS 17.4.4)。

特别是,post 响应假设 swvolatile-read(a.f) 之间存在 sw 关系volatile-write(a.f):没有这样的关系,执行恰好是这两个动作在 同步顺序,但由于没有sw关系,所以不需要引入适当的栅栏(事实上,在某些系统上你可能有read-acquire 后跟一个 store-release,它们不按那个顺序同步),或者,从另一个角度来看,没有 happens-before,所以存在数据竞争,实际行为是任何人的猜测,并且实际上可能 volatile-read(a.f) 读取 0 而不违反 JLS 17 中的任何内容。

编辑 1 的答案

   read(a, !null) (1)
      \--po--> vread(a.f, 0)
                    \---so---> vstore(a.f, 42)
                                    \---po---> store(a) (4)

Particullary, I don't undertand the above diagram: read(a, !null)(1) means that action read a and it is not-null whileas an action (4) store(a) stored to the a variable after (1).

Action 4 发生在与 Action 1 不同的线程中。因为 f 不是最终字段,而 store(a) 是不是易失性写入,受监视器保护,...没有任何强制订阅线程查看 vstore(a.f, 42)store( a) 的顺序。例如store(a)可以在vstore(a.f, 42).[=15=之前转发到另一个CPU ]

换句话说,图表具有误导性,最好分解为:

Synchronization Order:
    vread(a.f, 0) ---so---> vstore(a.f, 42)
Program Order in publishing thread:
    vstore(a.f, 42) ---po---> store(a)
Program Order in subscribing thread:
    read(a, !null) ---po---> vread(a.f, 0)

仅当程序 无竞争 时才使用单个图表才有意义,这意味着所有执行都需要看起来 sequentially-consistent,这看起来像是简单的线程交错。在没有 DRF-SC(数据竞争自由 - 顺序一致)行为的情况下,事情并没有那么简单。即便如此,我还是会推荐一个带有单独线程的图表,如下所示:

Publishing thread       Subscribing thread

                             read(a, !null)
                                  |
                                  po
                                  |
                                  v
                            vread(a.f, 0)
                          /     
                         so     
                        /       
                       v       
    vstore(a.f, 42)
       |
       po
       |
       v
    store(a) 

happens-before 顺序仅由 intra-thread program-order 的两个线程,并且根本没有 线程间 同步 排序。特别是,vread(a.f, 0)vstore(a.f, 42), 所以存在数据竞争,并不是程序的所有执行都需要看起来是顺序一致.

编辑 2 的答案

What does it mean vstore(A.f, null). I mean A.f is an int. So, why the author stores null to int? The same with vread(A.f, null)

在这种情况下,作者使用null来表示字段的默认值。这只是符号,不要读太多。