Java内存模型

Posted chenchenxiaobao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java内存模型相关的知识,希望对你有一定的参考价值。

内存模型

线程间通信
Java线程间的通信方式一般有共享内存及消息两种方式,其中消息通信一般为传统的wait()和notify()方法来实现线程间的显式通信。而另外一种则是采用共享内存来实现隐式通信。
 
内存模型概述
在Java内存模型(JMM)中,大致如下图所示:
?技术分享图片?
 
(1)、线程A将本地变更的副本刷新到主存中去;

(2)、线程B从主存中读取共享变量。

 

具体步骤如下图所示:

?技术分享图片?

 
 
指令重排序

1、编译器优化重排序(前提:不改变单线程程序语义);

2、现代处理器支持的指令级并行重排序(前提:不存在数据依赖性);

3、由于CPU通过缓存来实现读写,还会进行内存系统重排序。

如下图所示:

?技术分享图片?

其中1是属于编译器重排序,2和3是属于处理器重排序,在处理器重排序之前。JMM会要求编译器在生成

指令序列时要插入特定类型的内存屏障(Memory Barriers),通过内存屏障指令来禁止某些特定类型的处理器重排序。
 
重排序对多线程编程的影响
public class ReorderingTest {
  int a = 0;
  boolean flag = false;
 
  int result = 0;
 
  private void write() {
    a = 1;
    flag = true;
  }
 
  private void read() {
    if (flag) {
      result = a * a;
      System.out.println("result=" + result);
    }
  }
}
 
如果有两上线程A和B,线程A调用完write()方法之后,线程B去调用read()方法,result打印出来未必是1,也有可能是0。因为重排序可能导致线程A先执行flag=true,再执行a=1;因为在单线程环境下把a=0与flag=true并无依赖关系。
 
happens-before
在JMM中,如果一个操作的结果对于另一个操作是可见的,那么我们就说这两个操作之间存在着happens-before关系。
 
happens-before规则如下:
1、程序顺序规则:一个线程中的每一个操作都happens-before于后续的所有操作;
2、监视器锁规则:对一个锁的解锁,happens-before于对这个锁的加锁;
3、volatile变量规则:对一个volatile变量的写,都happens-before于任意后续对该变量的读;
4、传递性:如果A happens-before B,B happens-before C,那么A happens-before C。
 
注意:两个操作之间具有happens-before关系,不一定前一个操作必须要在后一个操作之前得到执行!happens-before规则仅仅只是要求前一个操作的结果对于后一个操作是可见的。
 

以上是关于Java内存模型的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Java内存模型

Java内存模型

Java内存模型

java内存模型的JMM简介

并发艺术--java内存模型

Java内存模型的历史变迁