Java内存模型FAQ(十三)为什么我需要关注java内存模型
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#conclusion
译者:Alex
为什么你需要关注java内存模型?并发程序的bug非常难找。它们经常不会在测试中发生,而是直到你的程序运行在高负荷的情况下才发生,非常难于重现和跟踪。你需要花费更多的努力提前保证你的程序是正确同步的。这不容易,但是它比调试一个没有正确同步的程序要容易的多。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#conclusion
译者:Alex
为什么你需要关注java内存模型?并发程序的bug非常难找。它们经常不会在测试中发生,而是直到你的程序运行在高负荷的情况下才发生,非常难于重现和跟踪。你需要花费更多的努力提前保证你的程序是正确同步的。这不容易,但是它比调试一个没有正确同步的程序要容易的多。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl
译者:Alex
臭名昭著的双重锁检查(也叫多线程单例模式)是一个骗人的把戏,它用来支持lazy初始化,同时避免过度使用同步。在非常早的JVM中,同步非常慢,开发人员非常希望删掉它。 阅读全文
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
译者:Alex
Volatile字段是用于线程间通讯的特殊字段。每次读volatile字段都会看到其它线程写入该字段的最新值;实际上,程序员之所以要定义volatile字段是因为在某些情况下由于缓存和重排序所看到的陈旧的变量值是不可接受的。编译器和运行时禁止在寄存器里面分配它们。它们还必须保证,在它们写好之后,它们被从缓冲区刷新到主存中,因此,它们立即能够对其他线程可见。相同地,在读取一个volatile字段之前,缓冲区必须失效,因为值是存在于主存中而不是本地处理器缓冲区。在重排序访问volatile变量的时候还有其他的限制。 阅读全文
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第九章
译者:Alex
一个对象的final字段值是在它的构造方法里面设置的。假设对象被正确的构造了,一旦对象被构造,在构造方法里面设置给final字段的的值在没有同步的情况下对所有其他的线程都会可见。另外,引用这些final字段的对象或数组都将会看到final字段的最新值。 阅读全文
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第八章
译者:Alex
我们可以通过分析String类的实现具体细节来展示一个final变量是如何可以改变的。
String对象包含了三个字段:一个character数组,一个数组的offset和一个length。实现String类的基本原理为:它不仅仅拥有character数组,而且为了避免多余的对象分配和拷贝,多个String和StringBuffer对象都会共享相同的character数组。因此,String.substring()方法能够通过改变length和offset,而共享原始的character数组来创建一个新的String。对一个String来说,这些字段都是final型的字段。
String s1 = "/usr/tmp";
String s2 = s1.substring(4);
字符串s2的offset的值为4,length的值为4。但是,在旧的内存模型下,对其他线程来说,看到offset拥有默认的值0是可能的,而且,稍后一点时间会看到正确的值4,好像字符串的值从“/usr”变成了“/tmp”一样。
旧的Java内存模型允许这些行为,部分JVM已经展现出这样的行为了。在新的Java内存模型里面,这些是非法的。
One of the best examples of how final fields’ values can be seen to change involves one particular implementation of the String class.
A String can be implemented as an object with three fields — a character array, an offset into that array, and a length. The rationale for implementing String this way, instead of having only the character array, is that it lets multiple String and StringBufferobjects share the same character array and avoid additional object allocation and copying. So, for example, the method String.substring() can be implemented by creating a new string which shares the same character array with the original String and merely differs in the length and offset fields. For a String, these fields are all final fields.
String s1 = "/usr/tmp";
String s2 = s1.substring(4);
The string s2 will have an offset of 4 and a length of 4. But, under the old model, it was possible for another thread to see the offset as having the default value of 0, and then later see the correct value of 4, it will appear as if the string “/usr” changes to “/tmp”.
The original Java Memory Model allowed this behavior; several JVMs have exhibited this behavior. The new Java Memory Model makes this illegal.
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第七章
译者:Alex
同步有几个方面的作用。最广为人知的就是互斥 ——一次只有一个线程能够获得一个监视器,因此,在一个监视器上面同步意味着一旦一个线程进入到监视器保护的同步块中,其他的线程都不能进入到同一个监视器保护的块中间,除非第一个线程退出了同步块。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第六章
译者:Alex
没有正确同步的代码对于不同的人来说可能会有不同的理解。在Java内存模型这个语义环境下,我们谈到“没有正确同步”,我们的意思是:
当这些规则被违反的时候,我们就说在这个变量上有一个“数据竞争”(data race)。一个有数据竞争的程序就是一个没有正确同步的程序。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第五章
译者:Alex
旧的内存模型中有几个严重的问题。这些问题很难理解,因此被广泛的违背。例如,旧的存储模型在许多情况下,不允许JVM发生各种重排序行为。旧的内存模型中让人产生困惑的因素造就了JSR-133规范的诞生。
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第三章
译者:Alex
从1997年以来,人们不断发现Java语言规范的17章定义的Java内存模型中的一些严重的缺陷。这些缺陷会导致一些使人迷惑的行为(例如final字段会被观察到值的改变)和破坏编译器常见的优化能力。
阅读全文
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第四章
译者:Alex
在很多情况下,访问一个程序变量(对象实例字段,类静态字段和数组元素)可能会使用不同的顺序执行,而不是程序语义所指定的顺序执行。编译器能够自由的以优化的名义去改变指令顺序。在特定的环境下,处理器可能会次序颠倒的执行指令。数据可能在寄存器,处理器缓冲区和主内存中以不同的次序移动,而不是按照程序指定的顺序。
阅读全文
原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第二章
译者:Alex
大部分其他的语言,像C和C++,都没有被设计成直接支持多线程。这些语言对于发生在编译器和处理器平台架构的重排序行为的保护机制会严重的依赖于程序中所使用的线程库(例如pthreads),编译器,以及代码所运行的平台所提供的保障。
原文地址:http://gee.cs.oswego.edu/dl/jmm/cookbook.html
作者:Doug Lea。由 JMM邮件组的成员提供帮助. dl@cs.oswego.edu.
译者:潘曦,丁一,古圣昌,欧振聪,方腾飞 校对:欧振聪,方腾飞
前言:从最初的探索至今已经有十年了。在此期间,很多关于处理器和语言的内存模型的规范和问题变得更清楚,更容易理解,但还有一些没有研究清楚。本指南一直在修订、完善来保证它的准确性,然而本指南部分内容展开的细节还不是很完整。想更全面的了解, 可以特别关注下 Peter Sewell和 Cambridge Relaxed Memory Concurrency Group的研究工作。
这是一篇用于说明在JSR-133中制定的新Java内存模型(JMM)的非官方指南。这篇指南提供了在最简单的背景下各种规则存在的原因,而不是这些规则在指令重排、多核处理器屏障指令和原子操作等方面对编译器和JVM所造成的影响。它还包括了一系列遵循JSR-133的指南。本指南是“非官方”的文档,因为它还包括特定处理器性能和规范的解释,我们不能保证所有的解释都是正确的,此外,处理器的规范和实现也可能会随时改变。
原文地址:http://gee.cs.oswego.edu/dl/jmm/cookbook.html 第一章 译者:欧振聪 校对:李同杰
对于编译器的编写者来说,Java内存模型(JMM)主要是由禁止指令重排的规则所组成的,其中包括了字段(包括数组中的元素)的存取指令和监视器(锁)的控制指令。
JMM中关于volatile和监视器主要的规则可以被看作一个矩阵。这个矩阵的单元格表示在一些特定的后续关联指令的情况下,指令不能被重排。下面的表格并不是JMM规范包含的,而是一个用来观察JMM模型对编译器和运行系统造成的主要影响的工具。
为了促进并发编程在中国的推广和研究,让更多的同学能阅读到国外的文献。所以打算将国外的编程文献翻译成中文,但是我一个人的精力有限,所以希望征集译者帮忙一起翻译。