读书笔记《JAVA并发编程的艺术》 第三章 Java内存模型 3.1 内存基础,
读书笔记《JAVA并发编程的艺术》 第三章 Java内存模型 3.1 内存基础,
3.1.1 - 3.1.2 Java并发基础与内存模型
在并发编程里,需要处理两个问题:线程之间如何通信及线程之间如何同步。通信指的是线程之间以何种机制来交换信息。在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传递。
Java的并发采用的是共享内存模型。
Java线程之间的通信由Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读、写共享变量的副本。
从图中可以看到,如果线程A和线程B之间要通信的话,必须经历如下的2步:
1)线程A把本地内存A中更新过的共享变量刷新到主内存中去;
2)线程B到主内存中去读取线程A之前已更新过的共享变量;
如图,假设初始时,本地内存A、B以及主内存中X均为0,线程A在执行时,把更新后的x值(假设为1)临时存放在自己的本地内存A中。当线程A和现场B需要通信时,线程A首先会把自己的本次内存中修改的x值刷新到主内存中,此时主内存中的x值变成了1。随后线程B到主内存中去读取线程A更新后的x值,此时线程B的本地内存中的x值也变成了1。
3.1.3 从源代码到指令序列的重排序
在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分为以下3种:
1)编译器优化的重排序
2)指令级并行的重排序
3)内存系统的重排序
从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图:
3.1.4 并发编程模型的分类
处理器 | 线程A | 线程B |
---|---|---|
代码 | a = 1 ; //A1 x = b; // A2 | b = 2;//B1 y = a; //B2 |
运行结果 | 初始状态:a=b=0;处理器允许执行后得到的结果:x = y = 0 |
为了保证内存可见性,java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。JMM把内存屏障指令分为4类:
3.1.5 happens-before简介
如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。这两个操作可以在同一个线程中,也可以在不同的线程中。
注意:两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见。
相关文章
- 暂无相关文章
用户点评