Java 发生在前,并且是可变的

Java 发生在前,并且是可变的,java,multithreading,concurrency,happens-before,Java,Multithreading,Concurrency,Happens Before,以下是JMM的三条“发生在”之前的规则。我没有列出其他规则,因为我的问题只涉及这三条规则 监视器锁定规则。监视器锁上的解锁发生在每次 同一监视器上的后续锁定锁定 线程开始规则。在线程上调用Thread.start发生在 已启动线程中的每个操作 中断规则。在另一个线程上调用中断的线程 在被中断线程检测到中断之前发生(或 通过抛出InterruptedException,或调用isInterrupted或 中断) 问题 第一个规则问题-假设两个线程A和B具有同步的代码块。第一条规则是否意味着线程

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

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

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

  • 第二条规则问题-假设线程a启动线程B。第二条规则是否意味着调用start()之前父线程中设置的任何变量都将对线程B可见,即使该变量未声明为volatile

  • 第三条规则问题-假设线程a中断线程B。第三条规则是否意味着在中断线程B之前在线程a中设置的任何变量在检测到中断后都将对线程B可见,即使该变量未声明为易失性

  • 最后,还有一个问题:

  • 在BlockingQueue文档中,据说, 内存一致性影响:与其他并发集合一样,将对象放入BlockingQueue之前的>线程中的操作发生在>另一个线程中从BlockingQueue访问或移除该元素之后的操作>之前

  • 这是否意味着,即使变量未声明为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
    的新值

    但是请注意!我上面的例子不包括任何方法来证明哪一个电话实际上是最先发生的。如果您的程序依赖于这些调用以特定的顺序进行,那么它需要的不仅仅是一个互斥锁:它需要一些方法使线程B
    wait()
    让线程a执行更新


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

    是的,这就是它的意思

    第三条规则问题

    是的

  • 。。。阻止队列
  • 是的


    …通过以上问题,我试图了解在这些事件之后是否会发生内存刷新,例如

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

    你需要担心的唯一概念是“以前发生过”


    每当JLS说A发生在B之前,这意味着如果A发生在线程1中,B发生在线程2中,并且您可以实时证明A确实发生在B之前,那么在A发生之前由线程1更新的任何字段都将保证在B发生之后在线程2中可见。

    4 x“是”。同一个问题重复了四次。但忘了“内存刷新”图片吧,这是错误的。写是可见的,到此为止。推荐——《Java并发实践》一书。