happens-before的规则对于程序员来说是很好理解的
它避免程序员为了理解JMM提供的内存可见性保证而去学习复杂的重排序规则以及这些规则的具体实现
我们先来说happens-before具体的规则以及个人的解读:
两个操作既可以是在一个线程之内,也可以是在不同线程之间。
1.程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
意思就是说前一个操作是对后续的操作都是可见性
2.锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;
前一个解锁的操作要对后面发生加锁操作是可见的
3.volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
对变量加上volatile后,后面对此变量执行读操作都是可见性的。
4.传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
5.线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
6.线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
7.线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
8.对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始
为了实现 happends-before ordering原则, java及jdk提供的工具:
a, synchronized关键字
b, volatile关键字
c, final变量
d, java.util.concurrent.locks包(since jdk 1.5)
e, java.util.concurrent.atmoic包(since jdk 1.5)
举个例子:
1) 获取对象监视器的锁(lock)
2) 清空工作内存数据, 从主存复制变量到当前工作内存, 即同步数据 (read and load)
3) 执行代码,改变共享变量值 (use and assign)
4) 将工作内存数据刷回主存 (store and write)
5) 释放对象监视器的锁 (unlock)
注意: 其中4,5两步是同时进行的.
这边最核心的就是第二步, 他同步了主内存,即前一个线程对变量改动的结果,可以被当前线程获知!(利用了happens-before ordering原则)
对比之前的例子
如果多个线程同时执行一段未经锁保护的代码段,很有可能某条线程已经改动了变量的值,但是其他线程却无法看到这个改动,依然在旧的变量值上进行运算,最终导致不可预料的运算结果
注:
参考:http://blog.sina.com.cn/s/blog_c038e9930102v1ot.html