【问题标题】:Inside Java synchronized static method: happens before relationship for static variableJava同步静态方法内部:发生在静态变量的关系之前
【发布时间】:2015-07-01 07:13:02
【问题描述】:

同步类方法中静态变量的更新是否保证之前发生过?以此为例:

public class MyClass {
    private static boolean isDone = false;

    public static synchronized doSomething() {
        if (!isDone) {
            // ...
        }

        isDone = true;
    } 
}

变量isDone(不是volatile)在此同步类方法中更新后是否对所有线程可见?据我了解,MyClass.class 上的同步本身并不能保证对其静态变量的所有更新对其他线程都是可见的,因为其他线程可能有一个本地缓存。

【问题讨论】:

  • 显然,不,因为读取在监视器上不同步
  • 无论如何,对于您的示例,如果变量仅在同步方法中使用,它将起作用

标签: java multithreading synchronized volatile java-memory-model


【解决方案1】:

happens-before 是两个事件之间的关系。您指出的事件之一:“更新到同步类方法中的静态变量”。你还有什么其他的想法?在另一个线程中简单地读取该变量?不,在另一个线程中的普通阅读不参与happens-before关系。

也就是说,您正确地建议同步并不能保证对变量的所有更新对其他线程都是可见的。

UPDT 为了保证对变量的所有更新对其他线程可见,线程还必须同步它们的读取,即在同步类方法中进行读取。

【讨论】:

  • 这就是我的想法.. 但请参阅上面我找到的引号。
  • 另一个事件应该是“在同步方法中读取另一个线程”
  • 引用说“我们购买了显示器”。其他线程必须获取监视器才能看到更新。
  • 对....所以如果其他线程执行同步的静态方法,他们将看到最新的值,因为监视器在所有线程中都是相同的。
【解决方案2】:

我在这里找到了答案:https://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#synchronization

退出同步块后,我们释放监视器,这具有将缓存刷新到主内存的效果,因此该线程所做的写入可以对其他线程可见。在我们进入同步块之前,我们获取了监视器,它具有使本地处理器缓存无效的效果,以便从主内存重新加载变量。然后,我们将能够看到以前版本中可见的所有写入。

【讨论】:

    【解决方案3】:

    以下是一种更简单的思考方式,如果您遵循良好的编码习惯:

    如果是synchronized,则不必担心。

    这是因为,如果线程 A 更新任何变量然后释放锁,那么在线程 B 锁定相同的锁之后,更新将对线程 B 可见,并且 如果 你遵循良好的编码习惯,那么您的 synchronized 块将尽可能小:您不会触及同步块内不需要同步的任何共享变量。而且,如果你遵循良好的编码习惯,那么每次对变量的访问(写或读)都会被同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多