【问题标题】:Understanding sequential consistency了解顺序一致性
【发布时间】:2014-05-12 14:43:09
【问题描述】:

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

线程 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 行,但这只是我的猜测。如果我从 Java 语言规范中看到这个解释,我会更加困惑:

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

如果是这样的话,我们会出队x

我确定我错了。有人可以解释一下吗?

【问题讨论】:

  • 是什么样的队列?先进先出?菲洛?
  • 哦,我忘了最重要的部分:它是先进先出
  • 您的错误是您假设 A 的动作作为一个整体以原子方式发生。它们分别是原子的。

标签: multithreading concurrency


【解决方案1】:

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

接着说:

如果程序没有数据竞争,那么程序的所有执行将看起来是顺序一​​致的。

(我强调“出现”)。

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 是非法的,因为存在与程序顺序一致的顺序一致的操作序列可以给出该结果。

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

【讨论】:

  • 谢谢,这真的很有帮助。我想我现在明白了。
猜你喜欢
  • 2018-04-04
  • 2016-04-09
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
相关资源
最近更新 更多