这段码是happens-before一致的,但不是真正的顺序一致。例如,如果r1看到为x=42的写入,并且r2看到Y=42的写入,x和y的值都是42,这是一个数据竞态条件的结果。
这里,写入变量都在读取变量之前,读取将看到相关的写入,这将导致OoTA结果。
注:数据竞态可能产生推测的结果,这将最终把自己变成自我实现的预言。OoTA保证是关于秉承因果关系的规则。目前的想法是,因果关系可以避免写入推测。JMM9旨在寻找OoTA的原因和改进方法,以避免OoTA。
为了禁止OoTA值,一些写入需要等待他们的读取来避免数据竞态。因此,JMM-JSR133定义的OoTA禁止正式拒绝OoTA读取。这个正式的定义包括内存模型的“执行和因果条件”。基本上,当所有的程序操作提交时,一个良好的执行要满足因果条件。
注:在每次读取可以看到对同一变量的写入时,一个良好的执行遵循在一个线程内、happens-before和synchronization-order一致地执行。
正如你可能已经知道的,JMM-JSR133定义严格定义,不让OoTA值侵袭。JMM9旨在发现和纠正正式的定义,以便允许一些常见的优化。
4. JMM9 非Volatile变量上的Volatile操作
首先,关键字'Volatile'是什么意思呢?Java的‘volatile’保证了线程间的交互,使得当一个线程写入一个volatile变量,不仅这次写入对其他线程可见,而且其他线程可以看到该线程所有的对volatile变量的写入。
那么对于non-volatile变量又发生了什么呢?非volatile变量没有volatile关键字保证交互的好处。因此,编译器可以使用non-volatile变量的缓存值而不是‘volatile’保证,‘volatile’变量将总是从内存中读取。happens-before模型可以用来绑定同步访问到非volatile变量上。
注:声明的任何字段为‘volatile’并不意味着有锁参与。因此volatile比使用锁来同步更便宜。但是着重要注意的是,当方法中有多个volatile字段时,可能比使用锁更昂贵。
5. JMM9 - 读写原子性问题和字分裂问题
JMM-JSR133也有为共享内存并行算法提供的读取和写入的原子性保证(使用异常)。异常是为non-volatile的长整型和双精度浮点型的写入被视为两个独立的写入而定义的。因此,一个64位的值可以分别写入两个32位,一个线程正在执行读的时候,如果其中的一个写入仍未完成,该线程可能会看到只有一半正确的值,从而失去原子性。这是原子性保证依赖于底层硬件和内存子系统的一个例子。例如,底层汇编指令应该能够处理的操作数的大小,以便保证原子性,否则如果读或写操作必须被分成多于一个的操作,最终将破坏原子性(正如例子中的non-volatile的长整型和双精度浮点型的值)。类似地,如果因为实现产生一个以上的内存子系统事务,那么也将破坏原子性。
注:volatile的长整型和双精度浮点型字段和引用始终保证读取和写入的原子性
基于位的设计不是一个理想的解决方案,因为如果64位的异常被删除,那么在32位的体系结构中就会受损。如果在64位架构上行不通,如果期望原子性,那么不得不为长整型和双精度浮点型引入“volatile”,即使底层硬件可以保证原子操作。例如:volatile类型的字段不需要定义为双精度浮点型,因为基础架构,或者ISA、浮点单元会处理好64位宽字段的原子性需求。JMM9的目的是确定硬件提供原子性的保证。
JMM-JSR133写于十多年前;此后处理器位数发生了演变,64位已经成为主流的处理位数。当即强调的是,JMM-JSR133提出了针对64位读写的妥协,尽管64位的值可以由任何架构原子生成,一些架构仍然有必要请求锁。现在,这使得在这些架构上的64位读写操作非常昂贵。在32位x86架构上,如果不能找到一个合理的原子64位操作实现,则原子性将不会改变。
注:在语言设计中潜在一个问题,关键字“volatile”被赋予了过分的含义。运行时很难弄清楚,用户使用volatile是为了恢复原子性(因此它可以在64位平台被剥离出来),还是为了内存排序的目的。
当谈论访问原子性,读写操作的独立性是要着重考虑的。写入一个特定的字段不应该与读取或者写入其他字段有交互。JMM-JSR133的保证意味着,同步不应需要提供顺序一致性。因此,JMM-JSR133保证禁止被称为“字分裂”的问题。基本上,当更新一个操作数希望在比基础架构为所有操作数生成的更低的粒度上操作时,我们将遇到“字撕裂”问题。需要记住的重要一点是,字撕裂问题的原因之一是,64位长整型和双精度浮点型都没有给出原子性保证。字撕裂在JMM-JSR133中是禁止的,在JMM9中继续保持这种方式。
6. JMM9 - final字段问题
与其他字段相比,final字段是不同的。例如,一个线程用final字段x读取一个“完全初始化”的对象;在对象“完全初始化”后,能保证读取了final字段y的初始值,但不能保证“正常”的非final字段nonX。
注:“完全初始化”是指对象的构造函数完成。
鉴于上述情况,有一些简单的事情可以在JMM9中修复。例如:volatile类型字段,volatile字段在构造函数中初始化是不保证可见性的,即使对实例本身是可见的。因此,问题来了,是否final字段应该保证扩大到所有字段,包括初始化volatile字段?此外,如果一个完全初始化对象的“正常”非final字段的值不发生变化,我们是否可以将final字段保证到这个“正常”的字段。
http://it.dataguru.cn/article-7676-1.html
相关推荐
Java内存模型是Java虚拟机规范中定义的一部分,它规定了Java程序中变量的读写行为,以及线程之间的交互规则。理解Java内存模型对于编写正确、高效的多线程程序至关重要。在Java 5之前,Java内存模型的描述比较模糊,...
- JSR133:JSR133是Java内存模型的重要修订,旨在修复早期JMM存在的问题,如内存可见性问题,提供更强的内存语义,并提高性能。它引入了对final和synchronized的新规则,以确保正确同步的代码行为明确且直观。 2. ...
Java内存模型(JMM)是Java编程中的一个重要概念,它规定了程序中各个变量的访问规则,尤其是在多线程环境下如何保证数据的一致性和可见性。JMM的目标是为了解决由于编译器优化、处理器缓存和多处理器系统间的内存...
### Java内存模型JSR-133详解 #### 引言 Java内存模型(Java Memory Model,简称JMM)是Java编程语言中的一个重要概念,它规定了程序中各种变量(线程共享变量)的访问规则,以及在并发环境中如何解决数据一致性...
JSR133是Java内存模型的一个重要修订,它旨在修复早期JMM存在的问题,提供更强的内存可见性和顺序一致性。JSR133引入了诸如final字段的保证、 volatile变量的强化以及对synchronized和volatile关键字的新解释,使得...
原始的Java内存模型存在一些不足,因此Java内存模型在Java1.5时被重新修订。这个版本的Java内存模型在Java8中人在使用。 Java内存模型内部原理 Java内存模型把Java虚拟机内部划分为线程栈和堆。这张图
对于Java特性的理解,例如多线程和内存管理,也是书中不可或缺的部分,这对于优化Web应用程序性能至关重要。 其次,书中详细讲解了Java在Web开发中的应用,主要围绕Servlet和JSP展开。Servlet是Java EE平台中的核心...
### Java理论与实践:修复Java内存模型,第1部分 #### 概述 活跃了将近三年的JSR133近期发布了一项关于如何修复Java内存模型(Java Memory Model, JMM)的重要建议。原始JMM中存在一些严重的缺陷,这导致了原本被...
JSR133,全称为Java Specification Request 133,是Java平台标准版(Java SE)的一个重要更新,它主要关注Java内存模型(Java Memory Model, JMM)的改进。这个规范对于理解Java并发编程至关重要,因为它解决了多...
此外,还可能涉及了Java内存模型(JMM)的理解,以及如何使用Lock接口和Condition来实现更细粒度的控制。 最后,[Java并发编程实践].(Java.Concurrency.in.Practice).Brian.Goetz.文字版(1).pdf可能是《Java并发...
九、JVM内存模型 了解JVM的工作原理,包括堆内存、栈内存、方法区、本地方法栈等,对于优化代码性能和避免内存泄漏至关重要。《剑指Offer》可能涉及对JVM的理解和应用。 总之,《剑指Offer》通过Java语言实现了众多...
1.7 Java内存模型(JMM)规定了线程如何访问和同步共享变量,以保证不同CPU核心上的线程看到的数据是一致的。JMM在Java1.5后进行了修订,以解决早期版本的一些问题,并一直沿用至今。 1.8.1 栈和堆是Java内存的两个...
10. **Java虚拟机(JVM)**:对JVM的理解,包括类加载机制、内存模型以及垃圾回收。 11. **标准API**:深入学习Java标准库中的各种类和方法,如JDBC、Swing、JavaMail等。 12. **设计模式**:常见的设计模式在Java...
12. **JVM原理**:了解Java虚拟机的工作原理有助于优化代码性能,书中可能涉及类加载、字节码执行、JVM内存模型等内容。 《Thinking in Java》中英双语版的特色在于,它不仅提供了原汁原味的英文原著,还配有中文...
2. **内存模型**:描述了Java虚拟机如何管理内存空间,包括方法区、堆、栈等区域的划分及其作用。 3. **垃圾回收机制**:介绍了垃圾回收的基本原理,包括标记-清除算法、复制算法、分代收集等策略。 4. **线程模型**...