发生在同步方法退出之前

时间:2016-09-02 13:00:56

标签: java multithreading

Oracle lesson on concurrency声明:

  

其次,当一个synchronized方法退出时,它会自动与同一个对象的同步方法的任何后续调用建立一个before-before关系。

这似乎很简单,因为“后续”意味着它在同步方法退出后发生。这种说法似乎也适用于非同步方法。我错过了什么?

2 个答案:

答案 0 :(得分:2)

你错过了“后续”与时间的流逝无关;它只能与方法调用在同步顺序中出现的位置一起使用。这是线性化(由挂钟时间严格排序,不受Java内存模型保证)和顺序一致性(“与某些排序一致”,保证之间的本质区别数据竞赛免费计划)。短语“之前发生”也具有欺骗性,因为它也不意味着时间排序。

对于未同步的方法,根本没有排序,因为它们的调用不会以同步顺序出现。

正如你在评论中非常好地总结一样:

  

每次执行都对同步操作有一些顺序,这些顺序可能与“实际”执行顺序相同或不同。但是,此同步顺序与各个线程的程序顺序一致。此外,如果在同步顺序中退出同步方法比在同一对象上输入同步方法更早,则输入方法中的所有读取都会在exited方法中进行写入。

答案 1 :(得分:0)

假设存在一个非易失性字段f,其中包含值 v ,并假设线程A使用值 w 更新字段f ,并假设线程B随后读取字段f

在更新和读取之间的关系之前,您可能会惊讶地发现 not 没有发生任何事情。 Java语言规范(JLS)允许线程B在读取字段时获取 v ,即使根据挂钟,读取发生在更新之后。

在一个线程中发生的一切都需要在程序顺序中进行。如果线程A执行的代码看起来像是更新某个字段,然后再读取该字段,那么JLS要求读取得到写入的值(即写入“在读取之前发生”)。

当读取和写入发生在不同的线程中时,没有这样的要求。通常,在某个特定情况下,在一个线程中发生的事件与另一个线程中发生的事件无关,除了。输入和离开synchronized块是其中一种特殊情况。

当JLS表示将同步块“在之前发生”后续进入同一对象上同步的块时,意味着在关系为真之前发生即使事件发生在不同的线程中也是如此。 / em>的