读final域的重排序规则是,在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM禁止处理器重排序这两个操作(注意,这个规则仅仅针对处理器)。编译器会在读final域操作的前面插入一个LoadLoad屏障。
写final域的重排序规则禁止把final域的写重排序到构造函数之外。这个规则的实现包含下面2个方面。1)JMM禁止编译器把final域的写重排序到构造函数之外。2)编译器会在final域的写之后,构造函数return之前,插入
3 6 final域的内存语义与前面介绍的锁和volatile相比,对final域的读和写更像是普通的变量访问。下面将介绍final域的内存语义。3 6 1 final域的重排序规则对于final域,编译器和处理器要遵守两个重排序规则。1
由于Java的CAS同时具有volatile读和volatile写的内存语义,因此Java线程之间的通信现在有了下面4种方式。1)A线程写volatile变量,随后B线程读这个volatile变量。2)A线程写volatile变量,随后B线程用CAS更新这个
本文将借助ReentrantLock的源代码,来分析锁内存语义的具体实现机制。请看下面的示例代码。class ReentrantLockExample { int a = 0; ReentrantLock lock = new ReentrantLock();
当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。以上面的MonitorExample程序为例,A线程释放锁后,共享数据的状态示意图如图3-25所示。当线程获取锁时,JMM会把该线程对应的本地内存置
3 5 锁的内存语义众所周知,锁可以让临界区互斥执行。这里将介绍锁的另一个同样重要,但常常被忽视的功能:锁的内存语义。3 5 1 锁的释放-获取建立的happens-before关系锁是Java并发编程中最重要的同步机制。锁
在JSR-133之前的旧Java内存模型中,虽然不允许volatile变量之间重排序,但旧的Java内存模型允许volatile变量与普通变量重排序。在旧的内存模型中,VolatileExample示例程序可能被重排序成下列时序来执行,如图3-
在JSR-133之前的旧Java内存模型中,虽然不允许volatile变量之间重排序,但旧的Java内存模型允许volatile变量与普通变量重排序。在旧的内存模型中,VolatileExample示例程序可能被重排序成下列时序来执行,如图3-
下面来看看JMM如何实现volatile写 读的内存语义。前文提到过重排序分为编译器重排序和处理器重排序。为了实现volatile内存语义,JMM会分别限制这两种类型的重排序类型。表3-5是JMM针对编译器制定的volatile重排序
volatile写的内存语义如下。当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。以上面示例程序VolatileExample为例,假设线程A首先执行writer()方法,随后线程B执行reader()方法
上面讲的是volatile变量自身的特性,对程序员来说,volatile对线程的内存可见性的影响比volatile自身的特性更为重要,也更需要我们去关注。从JSR-133开始(即从JDK5开始),volatile变量的写-读可以实现线程之间
3 4 volatile的内存语义当声明共享变量为volatile后,对这个变量的读 写将会很特别。为了揭开volatile的神秘面纱,下面将介绍volatile的内存语义及volatile内存语义的实现。3 4 1 volatile的特性理解volatile特
对于未同步或未正确同步的多线程程序,JMM只提供最小安全性:线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值(0,Null,False),JMM保证线程读操作读取到的值不会无中生有(Out Of Thin A
下面,对前面的示例程序ReorderExample用锁来同步,看看正确同步的程序如何具有顺序一致性。请看下面的示例代码。class SynchronizedExample { int a = 0; boolean f?lag = false;
顺序一致性内存模型是一个被计算机科学家理想化了的理论参考模型,它为程序员提供了极强的内存可见性保证。顺序一致性内存模型有两大特性。1)一个线程中的所有操作必须按照程序的顺序来执行。2)(不管程序是否
3 3 顺序一致性顺序一致性内存模型是一个理论参考模型,在设计的时候,处理器的内存模型和编程语言的内存模型都会以顺序一致性内存模型作为参照。3 3 1 数据竞争与顺序一致性当程序未正确同步时,就可能会存在
现在让我们来看看,重排序是否会改变多线程程序的执行结果。请看下面的示例代码。class ReorderExample { int a = 0; boolean f?lag = false; public void writer() {
根据happens- before的程序顺序规则,上面计算圆的面积的示例代码存在3个happens- before关系。1)A happens- before B。2)B happens- before C。3)A happens- before C。这里的第3个happens- bef
as-if-serial语义的意思是:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。为了遵守as-if-serial语义,编译器和处