快速业务通道

Java理论与实践: 修复Java内存模型,第1部分 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-07-04
同步的情况下不会做这种保证 —— 这就是只 要有多个线程访问相同的变量时必须使用同步(或者它的同胞,易失性)的原因 。

问题 1:不可变对象不是不可变的

JMM 的其中一个最惊人的缺点是,不可变对象似乎可以改变它们的值(这种 对象的不变性旨在通过使用 final 关键字来得到保证)。(Public Service Reminder:让一个对象的所有字段都为 final 并不一定使得这个对象不可变 — — 所有的字段 还 必须是原语类型或是对不可变对象的引用。)不可变对象( 如 String )被认为不要求同步。但是,因为在将内存写方面的更改从一个线程 传播到另一个线程时存在潜在的延迟,所以有可能存在一种竞态条件,即允许一 个线程首先看到不可变对象的一个值,一段时间之后看到的是一个不同的值。

这是怎么发生的呢?考虑到 Sun 1.4 JDK 中 String 的实现,这儿基本上有 三个重要的决定性字段:对字符数组的引用、长度和描述字符串开始的字符数组 的偏移量。 String 是以这种方式实现的,而不是只有字符数组,因此字符数组 可以在多个 String 和 StringBuffer 对象之间共享,而不需要在每次创建一个 String 时都将文本拷贝到一个新的数组里。例如, String.substring() 创建 了一个可以与原始的 String 共享同一个字符数组的新字符串,并且这两个字符 串仅仅只是在长度和偏移量上有所不同。

假设您执行以下的代码:

String s1 = "/usr/tmp"; String s2 = s1.substring(4);  // contains "/tmp"

字符串 s2 将具有大小为 4 的长度和偏移量,但是它将同 s1 共享包含“ /usr /tmp ”的同一字符数组。在 String 构造函数运行之前, Object 的构造 函数将用它们默认的值初始化所有字段,包括决定性的长度和偏移字段。当 String 构造器运行时,字符串长度和偏移量被设置成所需要的值。但是在旧的 内存模型下,在缺乏同步的情况下,有可能另一个线程会临时地看到偏移量字段 具有初默认值 0,而后又看到正确的值 4。结果是 s2 的值从“ /usr ”变成了 “ /tmp ”。这并不是我们所想要的,而且在所有 JVM 或平台这是不可能的, 但是旧的内存模型规范允许这样做。

问题 2:重新排序易失性和非易失性存储

另一个主要领域是与 volatile 字段的内存操作重新排序有关,这个领域中 现有 JMM 引起了一些非常混乱的结果。现有 JMM 表明易失性的读和写是直接和 主存打交道的,这样避免了把值存储到寄存器或者绕过处理器特定的缓存。这使 得多个线程一般能看见一个给定变量的最新的值。可是,结果是这种 volatile 定义并没有最初所想像的那样有用,并且它导致了 volatile 实际意义上的重大 混乱。

为了在缺乏同步的情况下提供较好的性能,编译器、运行库和缓存通常被允 许重新排序普通的内存操作,只要当前执行的线程分辨不出它们的区别。(这就 是所谓的 线程内似乎是串行的语义(within-thread as-if-serial semantics )。)但是,易失性的读和写是完全跨线程安排的,编译器或缓存不能在彼此之 间重新排序易失性的读和写。遗憾的是,通过参考普通变量的读和写,JMM 允许 易失性的读和写被重新排序,这意味着我们不能使用易失性标志作为操作已完成 的指示。考虑下面的代码,其意图是假定易失性字段 initialized 用于表明初 始化已经完成了。

清单 1. 使用一个易失性字段作为一个“守卫”变量

Map configOptions; char[] configText; volatile boolean initialized = false; . . // In thread A configOptions = new HashMap(); configText = readConfigFile(fileName); processConfigOptions(configText, configOptions); initialized = true; . . // In thread B while (

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号