以下是JMM的三个“发生之前”规则。我没有列出其他规则,因为我的问题只与这三条规则有关。
问题
> < li>
第一个规则问题-假设两个线程A和B有同步的代码块。第一条规则是否意味着线程A的同步块中设置的任何变量对线程B的同步块中的代码都是可见的,即使该变量没有声明为volatile?
第二个规则问题-假设一个线程A启动一个线程B。第二个规则是否意味着在调用start()之前在父线程中设置的任何变量对线程B都是可见的,即使该变量未声明为易失性?
第三个规则问题-假设线程a中断线程B。第三条规则是否意味着在中断线程B之前在线程a中设置的任何变量在检测到中断后对线程B都是可见的,即使该变量没有被声明为volatile?
最后,还有一个问题:
内存一致性效应:与其他并发集合一样,一个
这是否意味着在将对象从队列中取消排队后,线程 A 中设置的任何变量都将对线程 B 可见,即使该变量未声明为易失性?
基本上,通过以上问题,我试图理解内存刷新是否发生在这些事件之后,这样在这些情况下就不需要将变量声明为volatile。
第一个规则问题——假设两个线程A和B有同步的代码块。
线程没有代码。线程执行代码。
第一条规则是否意味着线程A的同步块中设置的任何变量对线程B的同步块中的代码都是可见的,即使该变量没有声明为volatile?
是的,假设我们有:
private int i;
private final Object lock = new Object();
void foobar(...) {
...
synchronized(lock) {
i = ...;
}
}
int getI() {
synchronized(lock) {
return i;
}
}
如果线程 A 调用 foobar
(),然后线程 B 随后调用 getI(),
则线程 B 将获得新的值 i
。
但是注意!我上面的例子不包括任何方法来证明哪个调用实际上是先发生的。如果你的程序依赖于这些调用以特定的顺序发生,那么它需要的不仅仅是一个互斥锁:它需要一些方法来让线程Bwait()
让线程A执行更新。
第二个规则问题-假设一个线程A启动一个线程B。第二个规则是否意味着在调用start()之前在父线程中设置的任何变量对线程B都是可见的,即使该变量未声明为易失性?
是的,就是这个意思。
第三条规则问题…
又是的。
又是的。
…通过以上问题,我试图理解这些事件之后是否发生了内存刷新,从而。。。
甚至不要考虑“内存冲洗”。这不是Java语言的一部分:如果发生这种情况,它是一个实现细节,除非你正在实现JVM,否则你不需要担心它。
你唯一需要担心的概念是“以前发生过”。
每当JLS说A发生在B之前,这意味着如果A发生在线程1中,而B发生在线程2中,并且您可以实时证明A确实发生在B之前,那么在A发生之前由线程1更新的任何字段都将保证在B发生后在线程2中可见。