内存可见性和happens-before原则
java-内存可见性
1.什么是内存可见性?
首先我们看下面这张图
java的运行机制来说,会为每个线程创建一个栈,线程运行的时候就会优先读取自己的工作内存内部的数据。然后在线程执行之后把数据在写会到主内存里面。但是多线程的条件下,可能会出现上一个线程还没有执行完的情况下,这个线程就要操作这个数据了,这个时候就会出现本线程去内存读到的数据和上一个线程内部的数据是不一致的。那么该如何保证一个数据在多线程之间是相同的呢?这就是内存可见性。
2.描述内存可见性的规则 happens-before 规则
简单来说就是如何A操作的结果是对B操作可见的,那么就必然存在A happens-before B的关系。注意他指的不是运行时间的先后而是可见性的先后顺序。java为了描述这种内存可见性的规则就提出了happens-before规则。
3.java里面一些天然存在的happens-before关系
① 程序顺序规则: 一个线程中的每个操作,happens-before于该线程中的任意后续操作(也就是说你写的操作,如果是单线程执行,那么前面的操作[程序逻辑上的前]就会happens-before于后面的操作)
② 监视器锁规则: 对一个锁的解锁,happens-before 于随后对这个锁的加锁
③ volatile变量规则: 对一个 volatile域的写,happens-before于任意后续对这个volatile域的读
④ 传递性:如果 A happens-before B,且 B happens-before C,那么A happens-before C
4.java主内存和工作内存交互的8个原子操作。
1.lock 将主内存的变量锁住。
2.unlock 主内存的变量解锁,其他线程可以获取这个变量
3.read 把主内存的变量读到写到工作内存里面
4.load 把read读取到的值存在本地的副本里面
5.usage 把本地变量的副本交给cpu执行
6.assign 把返回的结果复制给本地副本
7.store 把本地副本的值写到主内存
8.write 把主内存的值复制给主内存的变量
那么从jvm的层面来说就可以通过read和store这两个原子操作来保证内存可见性。就是读之前必须先执行read和load操作,写之后必须先执行store和write。
也就是所有的写必须happens-before读。