您的位置:首页 > 移动开发

Java内存 happens-before原则

2016-06-15 23:31 761 查看
在博客<< Java内存的三个特性>> 中已经解释过了可见性。

CPU的速度是远高于内存的,如果CPU总是需要和内存进行交互,那么CPU会在长时间内处于空闲状态,这样就会造成资源的浪费。这就出现了高速缓存:寄存器、多级cache . CPU对某一变量进行修改了之后,会将其存放到这些高速缓存中,在某个合适的时刻,这个变量的值会刷新进主内存,这在单线程环境下是没有问题的。在多线程环境下,何时将一个线程修改的变量值刷新进主内存,就意味着,另一个线程何时得到(见到)这个变量的值,这就是可见性的问题。

此外编译器为了加快效率会指令进行重排序,重排序后之后,执行顺序就与代码的顺序不一致了,可能线程A执行一条写入变量a的指令,而线程B此时执行读取变量a的指令,由于这两个线程执行顺序会被重排序,那么不同顺序的结果,肯定会不一致,这也是可见性的问题。

为此,java内存模型制定了一些规则,就是happens-before,这是一个偏序关系。

Monitor Lock Rule,它的英文解释:An unlock on a monitor happens-before every subsequent lock on that monitor.这短话直接翻译的话,依然会不理解,所谓何道。首先什么是Monitor,可以把他理解为一个对象,这个对象所有方法都被“互斥”的执行,任何一个线程执行方法时,必须获得这个方法的“许可”,即加锁,然后执行完,归还“许可”,即解锁。

这段话解释为:线程A解锁了 一个对象a,然后线程B马上对这个对象a进行加锁,那么线程A解锁对象a之前的所有写操作,都对线程B可见。

Volatile Variable Rule:英文原文:A write to a volatile field happens-before every subsequent read of that volatile. 这个理解就稍微简单点了。一个变量被volatie修饰,那么线程A对这个变量进行了写操作,线程B读取了这个变量,那么线程A对这个变量的写操作和之前的写操作,都对线程B可见。

Thread Termination Rule:All actions in a thread happen-before any other thread successfully returns from a join() on that thread.

线程A写入的所有变量,在任意其他线程B调用A.join()成功返回后,都对线程B可见。关于线程join的方法解释就是,如果在一个线程t1中调用t2.join(),那么此时线程t1 会被等待,而线程t2会执行,线程t2执行结束后,再继续执行线程t1.

**Program order rule:**Each action in a thread happens-before every subsequent action in that thread.

线程中上一个动作及之前的所有写操作在该线程执行下一个动作时对该线程可见(也就是说,同一个线程中前面的所有写操作对后面的操作可见)

Transitivity: If A happens-before B, and B happens-before C, then A happens-before C.

这个就是传递性性了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息