关键词:线性一致性 顺序一致性 弱一致性
一致性问题的解决思路是定义满足不同一致性需求的内存模型来解决内存一致性问题(Memory Consistency)。
JAVA内存模型给出的解决一致性问题的思路是定义一系列的Happens-before
规则来实现对共享变量同步操作的弱一致性需求。
happens-before
规则抽象地定义了多线程对共享变量的读写操作的偏序关系,实际上就是定义了在什么条件下一个线程对于共享变量的写操作对另一个线程可见。具体的讲,有:
- An unlock on a monitor happens-before every subsequent lock on that monitor. (同步锁和显式锁的可见性)
- A write to a volatile field happens-before every subsequent read of that field. (volatile共享变量的可见性)
- A call to start() on a thread happens-before any actions in the started thread. (start方法的可见性)
- All actions in a thread happen-before any other thread successfully returns from a join() on that thread. (join方法的可见性)
- The default initialization of any object happens-before any other actions (other than default-writes) of a program. (对象初始化方法的可见性)
- 程序次序规则:在单线程中,按照代码的执行顺序,(时间上)先执行的操作happen—before(时间上)后执行的操作
- 传递性:如果操作A
happens-before
操作B,操作Bhappens-before
操作C,那么操作Ahappens-before
操作操作C- 线程中断规则:对线程
interrupt
方法的调用happens-before
发生于被中断线程的代码检测到中断时事件的发生
仔细体会happens-before
规则是如何实现弱一致性需求的。
- 对于被同步的共享变量,保证弱一致性,通过加内存屏障(Memory Barrier)和缓存一致性协议实现,具体地讲:
- 读volatile变量或者进入锁,都会保证进入一致性;
- 写volatile变量或者释放锁,都会保证释放一致性;
- 同步变量的操作不允许进行指令重排序,保证了其顺序性;
- 对于没有被同步的共享变量,只保证其正确性,不保证其顺序性,具体地讲:
- 只保证其正确性,即从单线程执行的角度来说,程序的执行结果和程序定义的结果是一致性的;
- 不保证其顺序性,因为没有数据相关性的代码是可以重排序的;