JMM-多线程先行发生原则happens-before

5.6 JMM规范下多线程先行发生原则之happens-before

在JVM中,如果一个操作执行的结果需要对另一个操作可见或者代码重排序,那么这两个操作之间

必须存在happens-before(先行发生)原则,逻辑上的先后关系。

JMM-多线程先行发生原则happens-before_第1张图片

5.6.2 先行并发原则说明 

5.6.3 happens-before总原则

JMM-多线程先行发生原则happens-before_第2张图片5.6.4 happens-before之8条 

JMM-多线程先行发生原则happens-before_第3张图片

5.6.5 happens-before总结 

5.6.6 案例说明 

private int value =0;

public int getValue(){
    return value;
}

public int setValue(){
    return ++value;
}


问题描述:假设存在线程A和B,线程A先(时间上的先后)调用了setValue()方法,
然后线程B调用了同一个对象的getValue()方法,那么线程B收到的返回值是什么?

答案:不一定
分析happens-before规则(规则5,6,7,8可以忽略,和代码无关)
1 由于两个方法由不同线程调用,不满足一个线程的条件,不满足程序次序规则
2 两个方法都没有用锁,不满足锁定规则
3 变量没有使用volatile修饰,所以不满足volatile变量规则
4 传递规则肯定不满足
综上:无法通过happens-before原则推导出线程A happens-before 线程B,虽然可以确定时间上线程A优于线程B,但就是无法确定线程B获得的结果是什么,所以这段代码不是线程安全的

注意:
如果两个操作的执行次序无法从happens-before原则推导出来,那么就不能保证他们的有序性,
虚拟机可以随意对他们进行重排序

如何修复?

方法一:把getter/setter方法都定义为synchronized方法------->不好,重量锁,并发性下降

private int value =0;

public synchronized int getValue(){
    return value;
}

public synchronized int setValue(){
    return ++value;
}

方法二:把Value定义为volatile变量,由于setter方法对value的修改不依赖value的原值,满足

volatile关键字使用场景

你可能感兴趣的:(JUC并发编程与源码分析,jvm,java)