了解顺序一致性

时间:2014-05-12 14:43:09

标签: multithreading concurrency

假设有2个线程在共享队列q上执行操作。每个线程的代码行都有编号,最初队列为空。

主题A:

A1) q.enq(x) 
A2) q.deq()

主题B:

B1) q.enq(y)

假设执行顺序如下:

A1) q.enq(x)  
B1) q.enq(y)  
A2) q.deq()

因此我们得到y(即q.deq()返回y

这个执行是基于一本着名的书,据说是顺序一致的。请注意,方法调用不重叠。这怎么可能呢?我相信线程A执行A1而没有实际更新队列,直到它继续到A2行,但这只是我的猜测。如果我从The Java Language Specification中看到这个解释,我会更加困惑:

  

顺序一致性是对程序执行中的可见性和排序的有力保证。在顺序一致的执行中,所有单个操作(例如读取和写入)的总顺序与程序的顺序一致,并且每个单独的操作都是原子的,并且立即对每个线程可见。< /强>

如果是这种情况,我们就会出列x

我确定我错了。有人可以对此有所了解吗?

1 个答案:

答案 0 :(得分:2)

请注意,顺序一致性的定义表示“与程序顺序一致”,而不是“与程序执行顺序一致”。

接着说:

  

如果某个程序没有数据竞赛,那么程序的所有执行都将显示,以便顺序保持一致。

(我强调“出现”)。

Java的内存模型不强制执行顺序一致性。正如JLS所说:

  

如果我们使用顺序一致性作为我们的内存模型,我们讨论过的许多编译器和处理器优化都是非法的。例如,在表17.3的跟踪中,只要发生3到p.x的写入,就需要后续读取该位置才能看到该值。

因此,Java的内存模型实际上并不支持顺序一致性。只是顺序一致性的出现。而这只需要某些顺序一致的动作顺序与程序顺序一致。

显然,线程A和B的某些执行可能导致A2返回y,具体来说:

  

B1)q.enq(y)
  A1)q.enq(x)
  A2)q.deq()

因此,即使程序碰巧按照您指定的顺序执行,也有一个顺序可以执行“与程序顺序一致”,A2返回y。因此,在这种情况下返回y的程序仍然会呈现顺序一致的外观。

请注意,这不应被解释为说A2返回x是非法的,因为有一个顺序一致的操作序列与程序顺序一致,可以给出结果。< / p>

另请注意,顺序一致性的这种外观仅适用于正确同步的程序。如果你的程序没有正确同步(即有数据竞赛),那么所有的赌注都会关闭。