并发编程-Java内存模型:解决可见性与有序性问题
2020-12-08 12:55
标签:解决问题 java内存模型 volatile div start false 有序性 lse star 我们知道导致cpu缓存导致了可见性问题,编译器优化带来了有序性问题。那么如果我们禁用了cpu缓存与编译器优化,就能够解决问题,但是性能就无法提升了。所以一个合理的方案,就是按照一定规范来禁用缓存和编译器优化,即在某些情况下禁用缓存与编译器优化。Java内存模型就是这样的一个规范,用来解决可见性与有序性问题 java内存模型本质上就是规范了JVM如何按照规则禁用缓存和编译器优化,既面向应用开发人员,也面向jvm的实现。这些规范包括了volatile、synchronized和final三个关键字,以及六项Happens-Before规则。 volatile实质就是告诉编译器,对volatile修饰的变量,不能使用cpu缓存,必须从内存中读取或者写入。 HB本质是一种可见性,即前面一个操作结果对后面的操作是可见的,换句话说就是后面的操作能够看见前面的操作结果。HB约束了编译器的优化行为,允许优化,但是优化后的结果要符合HB规则 这条规则是指在一个线程中,按照程序顺序,前面的操作HB于后续的操作。 这条规则是指对一个 volatile 变量的写操作, HB于后续对这个变量的读操作。 这条规则是指A HB于 B,B HB于 C,那么A HB 于C。 当线程A执行完write方法,线程B执行read方法后,读到了v为true后,x是多少呢?首先在线程A中,根据同一线程顺序性规则,x=42 HB与v=true;再根据volatile变量规则,v=true的写操作HB于v的读操作;再根据传递性规则,x=42 HB于v的读操作,所以线程B中的值一定为42。在java并发包中的工具类,正是依靠这三条规则来实现可见性的 这条规则指对一个锁的解锁操作HB于后续对这个锁的加锁加锁操作 主线程A启动子线程B后,子线程B能够看到主线程在启动子线程之前的操作结果 在主线程A中等待子线程B完成(主线程A通过调用子线程B的join方法实现),当子线程完成后(主线程中的join方法返回),主线程能够看到子线程的操作结果 并发编程-Java内存模型:解决可见性与有序性问题 标签:解决问题 java内存模型 volatile div start false 有序性 lse star 原文地址:https://www.cnblogs.com/hello---word/p/10992069.html背景
概念
volatile
Happens-Before规则,简称为HB
同一线程顺序性规则
volatile变量规则
传递性
根据以上三条格则继续看下面的例子public class HappensBeforeDemo {
int x = 0;
volatile boolean v = false;
public void write(){
x = 42;
v = true;
}
public void read(){
if(v){
//x为多少呢
}
}
}
synchronized锁规则
线程start()规则
线程join规则
上一篇:深入理解Spring IoC
文章标题:并发编程-Java内存模型:解决可见性与有序性问题
文章链接:http://soscw.com/index.php/essay/23496.html