天天看点

java并发编程的艺术-Java内存模型

线程之间的通信机制:共享内存和消息传递

在共享内存的并发模型中,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。在消息传递的并发模型中,线程之间没有公共状态,线程之间必须通过发送消息来显式进行通信。

JAVA采用共享内存的并发模型

  1. java中,所有实例域、静态域、数组元素都存储在堆内存中,堆内存在线程之间共享。
    java并发编程的艺术-Java内存模型

    java线程之间的通信又java内存模型(JMM)控制,JMM决定了一个线程对共享变量的写入何时对另一个线程可见。

    线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存存储了该线程以读/写共享变量的副本。

    从上图看出,线程A和线程B要通信的话,需要经历一下步骤;

  2. 线程A把本地内存A中更新过的共享变量刷新到主内存中。
  3. 线程B到主内存读取线程A之前已更新过的共享变量

    JMM通过控制主内存与每个线程的本地内存之间的交互,来为java程序提供可见性保证。

    重排序

    java并发编程的艺术-Java内存模型

1:编译器优化重排序:编译器在不改变单线程程序语义的前提下,可以重排序

2:指令级并行的重排序:处理器在不存在数据依赖性的前提下,可以改变语句对应机器指令的执行顺序

3:内存系统的重排序:由于处理器使用缓存和读写缓存区,这使得加载和存储操作看起来的无序的

对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序。

对于处理器重排序,JMM的处理器重排序规则会要求编译器在生成指令前,插入特定类型的

内存屏障指令,通过内存屏障指令来禁止特定类型的处理器重排序。、

内存屏障有四类,

java并发编程的艺术-Java内存模型

在JMM中,如果一个操作执行的结果需要对另外一个操作可见,那么这两个操作之间必须存在happens-before关系.

如果两个操作访问同一个变量,其一个为写,那么这两个操作之间就存在数据依赖性。

as-if-serial 语义:不管怎么重排序,单线程的执行结果都不能被改变。遵守这个协议,处理器就不会对存在数据依赖性的操作做重排序。

java并发编程的艺术-Java内存模型

上面StoreStore 将保障上面所有的普通写在volatile写之前刷新到主内存。

java并发编程的艺术-Java内存模型

LoadLoad屏障用来禁止处理器把上面的volatile读与下面的普通读重排序。

LoadStore屏障用来禁止处理器把上面voaltile读与下面的普通写重排序。

继续阅读