简述:每个线程都有一个工作内存,它与主存独立,工作内存中存放主存变量的值的拷贝
- 数据从主内存复制到工作内存时,有两个操作:
1、对主内存执行读操作read
2、对工作内存执行相应的装载load
- 数据从工作内存拷贝到主内存时,有两个操作:
1、工作内存执行存储store
2、主内存执行相应的写操作write
线程通信要通过主存,JMM通过控制主内存与每个线程的本地内存之间的交互,来为程序提供内存可见性的保证
某线程修改了值,使用volatile可以让其他线程马上可见这个线程的改变
- 保证可见性的方法(同步原语):
1、volatile;
2、synchronized(同步解锁前,会写变量值回主存而且同步操作会变成顺序执行);
3、final一旦初始化完成,其他线程就可知
- 有序性概念:
1、在本线程内,操作都是有序的;
2、但是在线程外观察,对其他线程来说,操作又是无序的,因指令重排、主内存同步延迟等问题
3、指令重排:一个线程内,在不改变语义的情况下会改变各操作的执行顺序,但是多个线程的时候,编译器不会考虑多线程之间的语义。如:a=1;b=2;可重排,而a=2;b=a;有依赖的不可重排。
- 保证有序性方法:synchronized
即使做了重排,因为互斥,其他线程看到这个线程也将是有序的,可以理解为,即使重排了,但是使用同步以后,等锁释放了才会看到结果,那么重排是没有影响的
- 指令重排的原则:
1、程序顺序原则:一个线程内保证语义的串行性
2、volatile:happens-before原则,变量的写必发生于读
3、锁规则:happens-before原则,解锁unlock必发生于随后的加锁lock前
4、传递性:happens-before原则,A先于B,B先于C,那么A必然先于C
5、线程的start方法必先于它的每一个其他动作
6、线程的所有操作必先于线程的终结
7、线程的interrupt()先于被中断线程的代码
8、对象的构造函数执行结束先于finalize()方法