14. happens-before模型

1 happens-before产生背景

我们前面说过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题。那么我们正确使用同步、锁的情况下,线程A修改了变量a何时对线程B可见?

我们无法就所有场景来规定某个线程修改的变量何时对其他线程可见,但是我们可以指定某些规则,这规则就是happens-before,从JDK 5 开始,JMM就使用happens-before的概念来阐述多线程之间的内存可见性。也就说这仅仅是一种规则描述,而不是技术实现。

因此happens-before不仅仅局限于volatile,而是针对整个Java的,从JDK 5开始,Java使用新的JSR-133内存模型。JSR-133使用happens-before的概念来阐述操作之间的内存可见性。在JMM中,如果一 个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关 系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。

2 happens-before规则介绍

(1)程序顺序规则 1.不能改变程序的执行结果(在单线程环境下,执行的结果不变.) 2.依赖问题, 如果两个指令存在依赖关系,是不允许重排序 例如,这里的c=a*b一定要求前两个赋值完成才可以执行,但是这里并没要求b=1要早与a=1。

void test(){
int a=1; a
int b=1; b
int c=a*b; c
}

描述就是“b happens before c”。 需要注意的是,这个的含义是c执行的时候b的结果已经是可见的了,而不是规定指令执行的顺序。

(2)传递性规则 如果A happens-before B,且B happens-before C,那么A happens-before C (3)volatile变量规则 对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

再看个例子:

定义了一个变量
  volatile int a=0;
   
     a=10*2;
     System.out.print(a);    
public class VolatileExample {
    int a=0;
    volatile boolean flag=false;
    public void writer(){
        a=1;            1
        flag=true; //修改 2
    }  
    public void reader(){
        if(flag){ //true 3
            int i=a; //1 4
        }
    }
}

1 happens-before 2 是否成立? 是,为什么?这个是volatile导致的一条规则,记住就行了 。

3 happens-before 4 是否成立 是

然后有 2 happens -before 3 ->volatile规则

所以最终 1 happens-before 4 ; i=1成立

(4)监视器锁规则 对一个锁的解锁,happens-before于随后对这个锁的加锁。例如下面对x进行两次加锁,则前一个解锁一定早于下一个加锁操作。

 int x=10;
synchronized(this){
//后续线程读取到的x的值一定12
   if(x<12){
   x=12;
   }
}

start规则 这里其实也是为子线程的初始化提供条件。

 int x = 0;
        Thread t1 = new Thread(() -> {
//读取x的值 一定是20
            if (x == 20) {
           
            }
        });
        x = 20;
        t1.start();
    }

Join规则

public class Test{
int x=0;
Thread t1=new Thread(()->{
    x=200;
});
t1.start();
t1.join(); //保证结果的可见性。
//在此处读取到的x的值一定是200.
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵横千里,捭阖四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值