提问者:小点点

之前发生的和波动的变量


以下是JMM的三个“发生之前”规则。我没有列出其他规则,因为我的问题只与这三条规则有关。

    < li >监控锁定规则。一个监视器锁上的解锁发生在同一监视器锁上的每个后续锁之前。 < li >线程开始规则。在线程上调用Thread.start发生在启动的线程中的每个操作之前。 < li >中断规则。一个线程在另一个线程上调用中断发生在被中断的线程检测到中断之前(通过抛出InterruptedException,或者调用isInterrupted或interrupted)。

问题

> < li>

第一个规则问题-假设两个线程A和B有同步的代码块。第一条规则是否意味着线程A的同步块中设置的任何变量对线程B的同步块中的代码都是可见的,即使该变量没有声明为volatile?

第二个规则问题-假设一个线程A启动一个线程B。第二个规则是否意味着在调用start()之前在父线程中设置的任何变量对线程B都是可见的,即使该变量未声明为易失性?

第三个规则问题-假设线程a中断线程B。第三条规则是否意味着在中断线程B之前在线程a中设置的任何变量在检测到中断后对线程B都是可见的,即使该变量没有被声明为volatile?

最后,还有一个问题:

内存一致性效应:与其他并发集合一样,一个

这是否意味着在将对象从队列中取消排队后,线程 A 中设置的任何变量都将对线程 B 可见,即使该变量未声明为易失性?

基本上,通过以上问题,我试图理解内存刷新是否发生在这些事件之后,这样在这些情况下就不需要将变量声明为volatile。


共1个答案

匿名用户

第一个规则问题——假设两个线程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中可见。

相关问题