Happen-Before

JSR133给Java内存模型定义的happen-before规则

依然范特西╮ 提交于 2020-03-11 17:43:38
单线程规则:同一个线程中的每个操作都happens-before于出现在其后的任何一个操作。 对一个监视器的解锁操作happens-before于每一个后续对同一个监视器的加锁操作。 对volatile字段的写入操作happens-before于每一个后续的对同一个volatile字段的读操作。 Thread.start()的调用操作会happens-before于启动线程里面的操作。 一个线程中的所有操作都happens-before于其他线程成功返回在该线程上的join()调用后的所有操作。 一个对象构造函数的结束操作happens-before与该对象的finalizer的开始操作。 传递性规则:如果A操作happens-before于B操作,而B操作happens-before与C操作,那么A动作happens-before于C操作。 实际上这组happens-before规则定义了操作之间的内存可见性,如果A操作happens-before B操作,那么A操作的执行结果(比如对变量的写入)必定在执行B操作时可见。 为了更加深入的了解这些happens-before规则,我们来看一个例子: //线程A,B共同访问的代码 Object lock = new Object(); int a=0; int b=0; int c=0; //线程A,调用如下代码

[高并发Java 三] Java内存模型和线程安全

不想你离开。 提交于 2020-02-29 06:33:01
网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存。数据在主存中会有一份,在工作内存中也有一份。工作内存和主存之间会有各种原子操作去进行同步。 下图来源于 这篇Blog 但是由于Java版本的不断演变,内存模型也进行了改变。本文只讲述Java内存模型的一些特性,无论是新的内存模型还是旧的内存模型,在明白了这些特性以后,看起来也会更加清晰。 1. 原子性 原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。 一般认为cpu的指令都是原子操作,但是我们写的代码就不一定是原子操作了。 比如说i++。这个操作不是原子操作,基本分为3个操作,读取i,进行+1,赋值给i。 假设有两个线程,当第一个线程读取i=1时,还没进行+1操作,切换到第二个线程,此时第二个线程也读取的是i=1。随后两个线程进行后续+1操作,再赋值回去以后,i不是3,而是2。显然数据出现了不一致性。 再比如在32位的JVM上面去读取64位的long型数值,也不是一个原子操作。当然32位JVM读取32位整数是一个原子操作。 2. 有序性 在并发时,程序的执行可能就会出现乱序。 计算机在执行代码时,不一定会按照程序的顺序来执行。 class OrderExample { int a = 0; boolean flag = false;