7

我正在阅读实践中的 Java 并发

我对关于发生前关系的具体解释感到困惑。

它指出,

操作由称为happens-before的偏序排序

“部分排序”到底是什么意思?

(书中有解释,但我不清楚)

4

2 回答 2

6

偏序意味着不是每对操作都有关系happens-before

实际上,并非每对操作都具有这种关系这一事实使您能够同时执行操作。

例如,假设您有操作 A、B、C 和 D。

我们可以定义一个偏序:A must happen before B and C.

那么 A 和 B 有happens-before关系,A 和 C 也有。但是,A 和 D 没有这种关系,所以 D 可以在 A 之前、A 之后或在 A 执行时执行。

另一方面,如果happens-before是一个完整的排序,例如A happens-before B happens-before C happens-before D(请注意,在这种情况下,对于每一对操作,您都知道哪一个发生在另一个之前,因此它是一个完整的排序),那么操作的执行必须是串行的,并且不可能有并发。

于 2013-10-01T16:18:33.247 回答
3

由于您指的是“Java Concurrency in Practice”一书,我想您是关于 Java 内存模型的部分。

对于程序员来说,CPU 执行程序语句的顺序似乎很自然,因为它们在控制流中出现在源代码中。但是优化编译器、CPU 体系结构等几个因素强加了不同的低级行为。然而,这对于执行代码的线程是不可见的。它会表现得好像一切都按顺序发生。

这不再适用于多个线程。当关系存在之前没有发生时,线程可能会观察另一个线程的不同动作顺序。因此,对于这些操作,不存在指定的排序关系。例如当一个线程执行代码时

static Point XY;
…
XY = new Point(3, 4);

另一个线程可能会在该实例的和字段初始化之前观察到Point实例存储到字段中,从而看到 (0,0) 或 (3,0) 或 (0,4) 点。XYxy

XY因此,动作“赋值”、“赋值x”和“赋值y”与读取这些变量之间不存在顺序关系。

如果我们将变量声明更改为 volatile,则在将实例存储到该实例引用和读取该实例引用之间建立起XY发生前的关系。尽管如此, 和 的写入之间没有顺序,但是现在两个写入都与通过 读取这两个字段具有发生前的关系。PointXYxyXY

这就是部分排序;有些动作有顺序关系,有些则没有。

于 2013-10-01T22:09:22.233 回答