什么是Happens-before原则?

原子性、可见性、有序性这篇文章中,我们提到了为了实现并发编程、提高系统效率,我们引入了缓存、线程、编译优化,也因此引出了可见性、原子性、有序性问题。在并发编程中,我们就需要解决这三个问题。
原子性问题的解决放在下一篇。为了解决可见性、编译优化后指令顺序改变,我们需要禁用缓存、禁止编译优化。而这个过程是通过volatilesynchronizedfinal三个关键字以及6个happens-before规则来实现的。

happens-before的意思是:前面一个操作的结果对后续操作是可见的。
1.单线程规则:在一个线程中,前面的操作happens-before后面的操作。
2.volatile变量规则:一个对volatile变量的写操作,happens-before于后续的读操作
3.传递性规则:如果A happens-before B,B happens-before C。那么,A happens-before C
4.管程中的锁:对一个锁的解锁happens-before后续的加锁
5.线程start()规则:主线程A启动子线程B后,B能够看到A在启动B前的操作
6.线程join()规则:主线程A等待子线程B完成,当B完成后,A能看到B的操作

然后我们通过几个例子来加深理解:

规则1 2 3的应用

class VolatileExample {
  int x = 0;
  volatile boolean v = false;
  public void writer() {
    x = 42;
    v = true;
  }
  public void reader() {
    if (v == true) {
      // 读取到x = 42
    }
  }
}

在这里插入图片描述
根据规则1:x=42 happens-before v=true
根据规则2:写变量v=true happens-before 读变量v=true
根据规则3:x=42 happens-before 读变量v=true
所以说线程B读到的x=42.

规则4的应用

synchronized (this) { // 此处自动加锁
  // x 是共享变量, 初始值 =10
  if (this.x < 12) {
    this.x = 12; 
  }  
} // 此处自动解锁

假设由线程A先进入同步代码块,由于规则4,后进入的线程B能够看到A修改后的x值

规则5的应用

Thread B = new Thread(()->{
  // 主线程调用 B.start() 之前
  // 所有对共享变量的修改,此处皆可见
  // 此例中,x==77
});
// 此处对共享变量 var 修改
x = 77;
// 主线程启动子线程
B.start();

线程A修改共享变量x=77后启动子线程B,B可以看到x=77

规则6的应用

Thread B = new Thread(()->{
  // 此处对共享变量 x 修改
  x = 66;
});
// 例如此处对共享变量修改,
// 则这个修改结果对线程 B 可见
// 主线程启动子线程
B.start();
B.join()
// 子线程所有对共享变量的修改
// 在主线程调用 B.join() 之后皆可见
// 此例中,x=66

子线程B修改共享变量x=66,主线程A等待B结束后,可以看到x=66

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值