1:java内存模型的基础(JMM)
(1)并发编程模型的2个关键问题:共享内存和消息传递
如何理解这两个问题呢?(在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的功能状态进行隐式通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息来显示进行通信。)
(2)java中并发采用的是共享内存模型,java之间的通信总是隐式进行。
(3)java中,所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享。局部变量、方法定义参数和异常处理器参数不会在线程之间共享,他们不会有内存可见性问题。
(4)JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本。但是注意:它是一个抽象的概念,并不真实存在。
线程之间的通信图:
(5)从JAVA源代码到最终实际执行的指令序列,会分别经历下面3中重排序,如下图所示:
注意:2、3属于处理器重排序。
(6)为了保证内存可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。JMM把内存屏障指令分为4类,如下图所示:
(7)什么是happens-before?在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。下面说以下happen-before的原则:
a:程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
b:监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
c:volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
d:传递性:如果A happens-before B , 且B happens-before C, 那么A happens-before C.
重点注意:两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行。它仅仅是要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前。
2:重排序
(1)重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
(2)编译器和处理器重排序时会遵守数据依赖性,不会改变存在数据依赖关系的两个操作的执行顺序。
(3)as-if-serial语义的意思是:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。
3:顺序一致性
(1)计算机中,软件技术和硬件技术有一个共同的目标:在不改变程序执行结果的前提下,尽可能提高并行度。
(2)常用同步原语:sychronized、volatile和final
(3)数据竞争与顺序一致性
(4)顺序一致性内存模型
(5)同步程序的顺序一致性效果
(6)未同步程序的执行特征?
未同步程序在JMM模型和顺序一致性模型2个模型中的执行特性有下面几点差异:
a:顺序一致性模型保证单线程内的操作会按程序的顺序执行,而JMM不保证单线程内的操作会按程序的顺序执行(可以指令重排序)。
c:JMM不保证对64位的long型和double型变量的写操作具有原子性,而顺序一致性模型保证对所有的内存读/写操作都具有原子性。
(7)在计算机中,数据通过总线在处理器和内存之间传递。
4:volatile的内存语义
(1)一个volatile变量的单个读/写操作,与一个普通变量的读/写操作都使用同一个锁来同步。对一个volatile变量的读,总能看到(任意线程)对这个volatile变量最后的写入。因为锁的happens-before规则。
简而言之:volatile变量自身具有下列特性。
a:可见性 对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
b:原子性 对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。
(2)当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来从主内存中读取共享变量。
(3)volatile内存语义的实现:JMM针对编译器制定的volatile重排序规则表。
(4)《java理论与实践:正确使用volatile变量》
5:锁的内存语义
6:final域的内存语义
7:happens-before
(1)as-if-serial语义保证单线程内程序的执行结果不被改变,happens-before关系保证正确同步的多线程程序的执行结果不被改变。它们最终目的:都是为了在不改变程序执行结果的前提下,尽可能地提高程序执行的并行度。
(2)想想happens-before的规则???
8:双重检查锁定与延迟初始化
(1)线程安全的延迟初始化方案???
方案一:基于volatile的解决方案
方案二:基于类初始化的解决方案(JVM在类的初始化阶段【即在Class被加载后,且被线程使用前】,会执行类的初始化。在执行类的初始化期间,JVM会获取一个锁。这个锁可以同步多个线程对同一个类的初始化。)
注意一个优先级:volatile双重检查锁定方案除了可以对静态字段实现延迟初始化外,还可以对实例字段实现延迟初始化。
9:java内存模型概述
(1)各种内存模型之间的关系:JMM是一个语言及的内存模型、处理器内存模型是一个硬件级的内存模型、顺序一致性内存模型是一个理理参考模型。
(2)常见的4种处理器内存模型???常见的3中语言内存模型???
网友评论