美文网首页
五、【Java并发】JMM之happens-before

五、【Java并发】JMM之happens-before

作者: deve_雨轩 | 来源:发表于2021-08-24 16:53 被阅读0次

    happens-before

    happens-before是Java内存模型最核心的概念,因此理解happens-before是理解Java内存模型的关键。

    在Java语言中有个happens-before(先行发生)的原则。这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依据,依靠这个原则,我们就可以解决在并发环境中两个操作之间可能存在冲突的所有问题。下面我们来看个简单的例子:

    i = 1; //A线程执行
    j = i; //B线程执行
    i = 2; //C线程执行
    

    这里我们分两个情况来分析:

    • 线程C不执行
      假设A线程先行发生于线程B,根据先行发生原则那么就可以确定线程B执行完后,j一定等于1。
    • 线程C执行
      我们依然保持线程A先行与B线程,但此时线程C出现在线程A,B之间,假设线程C与线程B之间没有先行发生原则的话,此时j的值就不确定了!!!1和2都有可能,因为线程C对变量i的影响可能会被线程B观察到,也可能不会,这时候线程B就可能读取到过期数据的风险,不具备多线程安全性。

    happens-before规则

    Java内存模型下自带了写先行发生原则,这些先行发现原则无须任何同步器协助就已经存在,可以在编码中直接使用。如果两个操作之间的关系不在其中,并且无法从下面的规则推导出来的话,它们就没有顺序性保障,因为虚拟机可以对它们随意的进行重排序。

    • 程序次序规则:一个线程内,按照代码编写顺序,写在前面的操作happens-before写在后面的操作。但还是有可能指令重排,但随便怎么排,最后的结果应该和重排前代码顺序的结果是一致的。

    • 管程锁定规则:对于同一个锁来说,一个线程对这个锁解锁之后,另一个线程获取了这个锁都能看到前一个线程的操作结果。(管程是一种通用的同步术语,synchronized就是管程的实现)

    • volatile变量规则:就是如果一个线程先去写一个volatile变量,然后一个线程去读这个变量,那么这个写操作的结果对读的这个线程是可见的。对一个volatile变量的写操作happens-before后面对这个变量的读操作(这里针对的是指令重排);

    • 线程启动规则:Thread对象的start()方法happens-before此线程的每一个动作;在主线程A执行过程中,启动子线程B,那么线程A在启动子线程B之前对共享变量的修改结果对线程B可见。

    • 线程终止规则:线程中所有的操作都happens-before线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;在主线程A执行过程中,子线程B终止,那么线程B在终止之前对共享变量的修改结果在线程A中可见。

    • 线程中断规则:对线程interrupt()方法的调用happens-before被中断线程代码检测到中断事件的发生,可以通过Thread.interrupted()检测到是否发生中断。

    • 传递规则:就是happens-before原则具有传递性,即A happens-before B , B happens-before C,那么A happens-before C。

    • 对象终结规则:就是一个对象的初始化的完成,也就是构造函数执行的结束一定happens-before它的finalize()方法。

    相关文章

      网友评论

          本文标题:五、【Java并发】JMM之happens-before

          本文链接:https://www.haomeiwen.com/subject/prmliltx.html