并发程序的主要问题:在并发程序下数据访问的一致性和安全性问题。
JMM(Java的内存模型)则是为解决多个线程有效地、正确地协同工作而生。JMM的关键技术点都是围绕多线程的原子性、可见性、有序性来建立的。
原子性(Atomicity)
原子性是指一个操作不可中断的。
书中例子:以64位的long型的读写不是原子性为例。
可见性(Visibility)
指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
缓存优化、硬件优化、指令重排、编译器的优化,都有可能导致一个线程的修改不会立即被其他线程察觉。
有序性(Ordering)
有序性问题出现的原因是:程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。即:代码的执行并不一定是从先往后依次执行的。
那些指令不能重排:Happen-Before规则
java虚拟机和执行系统会对指令进行一定的重排,但是遵循一些原则的。
- 程序顺序原则:一个线程内保证语义的串行性(PS:多程序间的语义无法保证)
- volatile规则:volatile变量的写,先发生于读,这保证了volatile变量的可变性
- 锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
- 传递性:A先于B,B先于C,那么A必然先于C
- 线程中的start()方法先于它的每一个动作
- 线程中的所有操作先于线程的终结(Thread.join())
- 线程的中断(interrupt())先于被中断线程的代码
- 对象的构造函数执行、结束先于finalize()方法