`
oojdon
  • 浏览: 39729 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

JMM和Happen Before

阅读更多

 

线程是操作系统的最小调度单位,也是执行单位,为了追求高性能,线程里面的指令执行顺序是不定的,这来自编译器会重排序指令,处理器会乱序或者并行的执行,编译器还有可能将数据放在处理器的寄存器中等,这些优化技术在单线程的程序中表现得很好,但是到了多线程程序中就有问题了。

 

首先要了解下Java的内存结构,然后我们再进入线程和内存的关系, Java的内存结构如下


 

如果多线程之间不共享数据,这也表现得很好,但是如果多线程之间要共享数据,那么这些乱序执行,数据在寄存器中这些行为将导致程序行为的不确定性,现在处理器已经是多核时代了,这些问题将会更加严重,每个线程都有自己的工作内存,多个线程共享主内存,如图


 

如果共享数据,什么时候同步到主内存让别人的线程读取数据呢?这又是不确定的,如果非要一致,那么代价高昂,这将牺牲处理器的性能,所以现在的处理器会牺牲存储一致性来换取性能,如果程序要确保共享数据的时候获得一致性,处理器通常了提供了一些关卡指令,这个可以帮助程序员来实现,但是各种处理器都不一样,如果要使程序能够跨平台是不可能的,怎么办?

 

使用Java,JMM来屏蔽,我们只要和JMM的规定来使用一致性保证就搞定了,那么JMM又提供了什么保证呢?JMM的定义是通过动作的形式来描述的,所谓动作,包括变量的读和写,监视器加锁和释放锁,线程的启动和拼接,这就是传说中的happen before,要想A动作看到B动作的结果,BA必须满足happen before关系,happen before法则如下:

 

 

1, 程序次序法则,如果A一定在B之前发生,则happen before,

2, 监视器法则,对一个监视器的解锁一定发生在后续对同一监视器加锁之前

3, Volatie变量法则:写volatile变量一定发生在后续对它的读之前

4, 线程启动法则:Thread.start一定发生在线程中的动作

5, 线程终结法则:线程中的任何动作一定发生在括号中的动作之前(其他线程检测到这个线程已经终止,从Thread.join调用成功返回,Thread.isAlive()返回false)

6, 中断法则:一个线程调用另一个线程的interrupt一定发生在另一线程发现中断。

7, 终结法则:一个对象的构造函数结束一定发生在对象的finalizer之前

8, 传递性:A发生在B之前,B发生在C之前,A一定发生在C之前。

 

  • 大小: 28.3 KB
  • 大小: 10.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics