繁体   English   中英

发生前和可变变量

[英]Happens-before and volatile variable

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

  • 监视锁定规则。 监视器锁的解锁发生在该监视器锁上的每个后续锁之前。
  • 线程启动规则。 在启动线程中的每个操作之前,都会在线程上调用Thread.start。
  • 中断规则。 一个线程在另一个线程上调用中断发生在被中断的线程检测到中断之前(通过引发InterruptedException或调用isInterrupted或被中断)。

问题

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

  2. 第二条规则问题 -假设一个线程A启动了一个线程B。第二条规则是否意味着即使在该变量未声明为volatile的情况下,调用start()之前在父线程中设置的任何变量对线程B也是可见的?

  3. 第三条规则问题 -假设一个线程A中断了一个线程B。第三条规则是否意味着在检测到中断后,线程A在线程A之前设置的任何变量在线程B之前对线程B都是可见的,即使该变量未声明为挥发性?

最后,还有一个问题:

  1. 在BlockingQueue文档中说,

    内存一致性影响:与其他并发集合一样,在将对象放入BlockingQueue之前,在>线程中执行的操作要先于在另一个线程中的BlockingQueue中访问或删除该元素之后的操作。

这是否意味着在将对象从队列中出队后,线程A中在将对象放入队列中之前在线程A中设置的任何变量对于线程B都是可见的,即使该变量未声明为volatile也不行?

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

第一个规则问题-假设两个线程A和B具有同步的代码块。

线程不必代码。 线程执行代码。

第一条规则是否意味着即使未将变量声明为volatile,线程A的同步块中设置的任何变量对于线程B的同步块中的代码也将可见?

是的,假设我们有:

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的新值。

但是请注意! 我上面的示例没有提供任何方法来证明哪个呼叫最先发生。 如果您的程序依赖于以特定顺序发生的那些调用,那么它不仅需要互斥锁:它还需要一些方法来使线程B wait()使线程A执行更新。


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

是的,就是这个意思。

第三条规则问题...

再来一次

  1. ... BlockingQueue ...

再来一次


通过上述问题,我试图了解在这些事件之后是否发生了内存刷新,从而...

甚至不要考虑“内存刷新”。 那不是Java语言的一部分:如果发生这种情况,那是实现细节,除非您正在实现 JVM,否则不必担心。

您唯一需要担心的概念是“发生之前”。

只要JLS说A 发生在 B 之前 ,就意味着如果A发生在线程1中,而B发生在线程2中,并且您可以实时证明 A确实确实发生在B之前,那么任何由保证A发生之前的线程1在B发生之后在线程2中可见。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM