Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(三)

⑤. JVMM规范下,多线程先行发生原则之happens-before


①. 先行发生原则说明



①. 如果Java内存模型中有序性仅靠volatile和synchronized来完成,那么有很多操作都将会变得非常啰嗦,但是我们在编写Java并发代码的时候并没有察觉到这一点


②. 我们没有时时、处处、次次,添加volatile和synchronized来完成程序,这是因为Java语言中JMM原则下,有一个"先行发生"(Happens-Before)的原则限制和规则


③. 在JMM中,如果一个操作执行的结果需要对另一个操作可见性或者代码重排序,那么这两个操作之间必须存在happens-before关系


④. x、y案例说明


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(三)


②. happens-before总原则


①. 如果一个操作happens-before另一个操作,那么第一个操作的执行结果对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前(可见性,有序性)


②. 两个操作之间存在happens-before关系,并不意外着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序并不非法(可以指令重排)


(值日:周一张三周二李四,假如有事情调换班可以的1+2+3=3+2+1)


③. happens-before之8条


①. 次序规则


一个线程内,按照代码顺序,写在前面的操作先行发生于写在后面的操作(强调的是一个线程)


前一个操作的结果可以被后续的操作获取。将白点就是前面一个操作把变量X赋值为1,那后面一个操作肯定能知道X已经变成了1


②. 锁定规则


(一个unlock操作先行发生于后面((这里的"后面"是指时间上的先后))对同一个锁的lock操作(上一个线程unlock了,下一个线程才能获取到锁,进行lock))


③. volatile变量规则


(对一个volatile变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的,这里的"后面"同样是指时间是的先后)


④. 传递规则


(如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出A先行发生于操作C)


⑤. 线程启动规则(Thread Start Rule)


(Thread对象的start( )方法先行发生于线程的每一个动作)


⑥. 线程中断规则(Thread Interruption Rule)


对线程interrupt( )方法的调用先发生于被中断线程的代码检测到中断事件的发生

可以通过Thread.interrupted( )检测到是否发生中断


⑦. 线程终止规则(Thread Termination Rule)


(线程中的所有操作都先行发生于对此线程的终止检测)


⑧. 对象终结规则(Finalizer Rule)


(对象没有完成初始化之前,是不能调用finalized( )方法的 )


④. 案例说明


①. 代码展示、问题暴露、解决方案


    private int value=0;
    public void setValue(){
        this.value=value;
    }
    public int getValue(){
        return value;
    }


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(三)


②. 解决方案


把getter/setter方法都定义synchronized方法(某一时刻只能有一个线程进入)

把value定义为volatile变量,由于setter方法对value的修改不依赖value的原值,满足volatile关键字的使用


(对一个volatile变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的,这里的"后面"同样是指时间是的先后)


上一篇:线程优先级|学习笔记


下一篇:多源复制环境下数据的校验与修正