Hello 大家好,我原名叫Java Memory Model(Java 内存模型),大家都叫我JMM,简洁又好听!并发编程这块,没有我可是不行的,我要解决的问题就是一个线程对共享变量的写入何时对另一个线程可见!
比如一个线程给变量 a 赋值 int a = 3; // 向变量 a 写值
我要解决的问题就是:"在什么条件下,读取变量a的线程将看到这个值3"
如果缺少同步,那会有很多因素使得读取变量a的线程不能立即看到或者永远看不到这个值3 在我的世界里,所有的变量都存储在主内存中, 每一个线程都有一个私有的本地内存,本地内存中存储了该线程使用到的变量在主内存中拷贝!
线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量也不例外)
happens-before概念:
那什么是 happens-before规则呢?
举个例子:
i = 1; // 操作 A
j = i; // 操作 B
如果操作A happens-before 于操作B,那么就可以确定,操作B执行完之后,j 的值一定
为 1;因为happens-before关系可以向程序员保证:在操作B执行之前,操作A的执行后的
影响[或者说结果](修改 i 的值)操作B是可以观察到的[或者说可见的]
换句话说,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须
要存在happens-before关系,在这个例子就是A操作的结果要对B操作可见,那么必然存在A
happens-before B
简而言之:使用happens-before的概念来阐述操作之间的内存可见性
happens-before规则
程序顺序规则:
一个线程中的每个操作,happens-before于该线程中的任意后续操作(也就是说你写的操作,
如果是单线程执行,那么前面的操作[程序逻辑上]就会happens-before于后面的操作)这里
的影响指修改了 i 变量的值
监视器锁规则:
对一个锁的解锁,happens-before 于随后对这个锁的加锁
volatile变量规则:
对一个 volatile域的写,happens-before于任意后续对这个volatile域的读
传递性规则:
如果 A happens-before B,且 B happens-before C,那么A happens-before C
指令的重排序
传递性在JDK中,JAVA语言为了维持顺序内部的顺序化语义,也就是为了保证程序的最终运行结果需要和在单线程严格意义的顺序化环境下执行的结果一致,程序指令的执行顺序有可能和代码的顺序不一致,这个过程就称之为指令的重排序。指令重排序的意义在于:JVM能根据处理器的特性,充分利用多级缓存,多核等进行适当的指令重排序,使程序在保证业务运行的同时,充分利用CPU的执行特点,最大的发挥机器的性能!