专栏首页Krainshappens-before Krains 2020-08-26

happens-before Krains 2020-08-26

happens-before 规定了对共享变量的写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,抛 开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见

线程解锁m之前对变量的写,对于接下来对 m 加锁的其它线程对该变量的读可见

static int x;
static Object m = new Object();

// 线程t1先于t2执行,由于加了锁,t1对共享变量的修改对t2可见
new Thread(()->{
    synchronized(m) {
    	x = 10;
    }
},"t1").start();

new Thread(()->{
    synchronized(m) {
    	System.out.println(x);
    }
},"t2").start();

线程对 volatile 变量的写,对接下来其它线程对该变量的读可见

volatile static int x;

// 线程t1先于t2执行,由于关键字volatile,t1对共享变量的修改对t2可见
new Thread(()->{
	x = 10;
},"t1").start();

new Thread(()->{
	System.out.println(x);
},"t2").start();

线程start前对变量的写,对该线程开始后对该变量的读可见

static int x;

x = 10;

new Thread(()->{
	System.out.println(x);
},"t2").start();

线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用 t1.isAlive() 或 t1.join()等待它结束)

static int x;

Thread t1 = new Thread(()->{
	x = 10;
},"t1");
t1.start();

t1.join();
System.out.println(x);

线程 t1 打断 t2(interrupt)前对变量的写,对于其他线程得知 t2 被打断后对变量的读可见(通过t2.interrupted 或 t2.isInterrupted)

static int x;

public static void main(String[] args) {
    Thread t2 = new Thread(()->{
        while(true) {
            if(Thread.currentThread().isInterrupted()) {
                System.out.println(x);
                break;
        	}
    	}
    },"t2");
    t2.start();
    
    new Thread(()->{
        Thread.sleep(1000);
        x = 10;
        t2.interrupt();
    },"t1").start();
    
    while(!t2.isInterrupted()) {
    	Thread.yield();
    }
    System.out.println(x);
}

对变量默认值(0,false,null)的写,对其它线程对该变量的读可见

具有传递性,如果 x -> y 并且 y -> z 那么有 x -> z ,配合 volatile 的防指令重排,有下面的例子

volatile static int x;
static int y;

new Thread(()->{
    y = 10;
    x = 20;
},"t1").start();

new Thread(()->{
    // x=20 对 t2 可见, 同时 y=10 也对 t2 可见
    System.out.println(x);
},"t2").start();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • volatile关键字 Krains 2020-08-26

    main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止

    Krains
  • 96. 不同的二叉搜索树 II Krains 2020-09-03 树

    但是如果按照上述递归函数的方法写,每次递归只能返回一颗树,我们需要的是多颗树,我们可以将不同的根结点装入List然后返回,实际上,上述代码可以改写成

    Krains
  • ReentrantLock可重入锁 Krains 2020-08-27

    与 synchronized 一样,都支持可重入,但相对于 synchronized 它还具备如下特点

    Krains
  • 简说Java线程的那几个启动方式

    并发是一件很美妙的事情,线程的调度与使用会让你除了业务代码外,有新的世界观,无论你是否参与但是这对于你未来的成长帮助很大。

    Java猫说
  • Godot3游戏引擎入门之六:制作TileMap瓦片地图

    2018-10-19 by Liuqingwen | Tags: Godot | Hits

    IT自学不成才
  • 机器学习的最直白讲解,就看这篇!

    假如你想深入机器学习和它背后的数学,你将会很快意识到一切都可归结为一个优化问题。就连训练神经网络都是一个参数优化的问题。因此要想理解机器学习算法,你需要首先理解...

    double
  • 机器学习的最直白讲解,就看这篇!

    假如你想深入机器学习和它背后的数学,你将会很快意识到一切都可归结为一个优化问题。就连训练神经网络都是一个参数优化的问题。因此要想理解机器学习算法,你需要首先理解...

    石晓文
  • 互联网奠基人:温顿·瑟夫自曝新冠病毒检测呈阳性

    场景描述:互联网奠基人之一:温顿·瑟夫(Vinton G. Cerf) ,3 月 30 日在自己的推特上发布自己冠状病毒检测呈阳性。

    HyperAI超神经
  • conky主题Harmattan安装和介绍

    Harmattan是一款conky主题,安装和使用都很简单,而且提供了很多样式,方便你选择。

    bboysoul
  • [十三]JavaIO之PushBackInputStream

    看得出来,如果你从来不曾回退过,那么好像什么都一样,还是使用原来的InputStream 进行读取

    noteless

扫码关注云+社区

领取腾讯云代金券