【问题标题】:Understanding Happens-Before-Relationship了解发生之前的关系
【发布时间】:2017-06-24 12:48:38
【问题描述】:

考虑以下类:

public myClass {
    int a;
    Object obj;    //This object is not of class myClass nor of a subclass of it.

    void foo(int b){
        synchronized(this){
            print(a);
            a = b;
            obj.value = b;
            obj.bar();
        }
    }

    void bar(){
        synchronized(this){
            //Some code using obj here.
        }
    }

}

Java 文档指出:

当线程释放内在锁时,会在该操作与任何后续获取同一锁的操作之间建立起之前的关系。

假设有两个线程 T1、T2 和一个名为 myclass 的 myClass 对象。

现在 T1 调用 foo,不久之后 T2 调用 bar 并最终获得锁并进入 bar()。如果错了,请纠正我,但据我了解,T2 请参阅 T1.foo(b) 中对变量 a 所做的更改。对 obj 所做的更改如何?将其视为任意其他对象。

是否保证发生之前的关系?

【问题讨论】:

  • 您的源代码并不是真正的 Java。 int Object obj 没有意义,如果objObject,则它没有valuebar() 方法。你应该清理你的例子。
  • 对不起那个错字,我试图澄清。

标签: java multithreading concurrency


【解决方案1】:

是:T2 获得了 T1 已经释放的锁。因此存在先发生的关系,因此在 T1 获得锁之后,T1 在释放锁之前所做的写入对 T2 是可见的。

http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility

请注意,它是关于内存操作,例如共享变量的读取和写入。不仅读取和写入用作锁的对象的字段。

【讨论】:

  • 在我的示例中,对 obj.bar() 的调用很可能会调用自己的其他函数,这反过来可能会改变其他对象等。这是否也包括在内?所以当在我的示例中使用时,T2 将看到我的函数调用 T1 所做的一切,当然只有同步块中的那些更改,没有限制?
  • 所以实际上我想知道的是,为了确保我正确理解你,当 A 获取锁,B 释放和获取锁时。B 能够看到任何更改我们当前 JVM 环境中的任何对象/变量由 A 完成,而 A 持有锁?
  • 是的,就是这样。
  • 哇,就我们用这么少的代码得到的东西而言,这真是太棒了……谢谢!
  • 实际上,它会看到A在释放锁之前所做的所有更改。包括在它获得它之前制造的那些,而不仅仅是在持有锁时。
猜你喜欢
  • 1970-01-01
  • 2021-02-06
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多