第6章 Java并发编程实践.pdf

  1. 1、本文档被系统程序自动判定探测到侵权嫌疑,本站暂时做下架处理。
  2. 2、如果您确认为侵权,可联系本站左侧在线QQ客服请求删除。我们会保证在24小时内做出处理,应急电话:400-050-0827。
  3. 3、此文档由网友上传,因疑似侵权的原因,本站不提供该文档下载,只提供部分内容试读。如果您是出版社/作者,看到后可认领文档,您也可以联系本站进行批量认领。
查看更多
第二章 构建线程安全应用程序 第二章 构建线程安全应用程序1 2.1. 什么是线程安全性2 2.2. Servlet的线程安全性5 2.3. 同步与互斥9 2.3.1 线程干扰9 2.3.2 同步11 2.4. 同步与volatile13 2.5. 活性 14 2.6. ThreadLocal变量 15 2.7. 高级并发对象19 参考文献 20 2.1. 什么是线程安全性 当对一个复杂对象进行某种操作时,从操作开始到操作结束,被操作的对象往往会经历 若干非法的中间状态。这跟外科医生做手术有点像,尽管手术的目的是改善患者的健康,但 医生把手术过程分成了几个步骤,每个步骤如果不是完全结束的话,都会严重损害患者的健 康。想想看,如果一个医生切开患者的胸腔后要休三周假会怎么样?与此类似,调用一个函 数(假设该函数是正确的)操作某对象常常会使该对象暂时陷入不可用的状态 (通常称为不 稳定状态),等到操作完全结束,该对象才会重新回到完全可用的状态。如果其他线程企图 访问一个处于不可用状态的对象,该对象将不能正确响应从而产生无法预料的结果,如何避 免这种情况发生是线程安全性的核心问题。单线程的程序中是不存在这种问题的,因为在一 个线程更新某对象的时候不会有其他线程也去操作同一个对象。(除非其中有异常,异常是可 能导致上述问题的。当一个正在更新某对象的线程因异常而中断更新过程后,再去访问没有 完全更新的对象,会出现同样的问题) 给线程安全下定义是比较困难的。很多正式的定义都比较复杂。如,有这样的定义:“一 个类在可以被多个线程安全调用时就是线程安全的”。但是它不能帮助我们区分一个线程安 全的类与一个线程不安全的类。 实际上,所有线程安全的定义都有某种程序的循环,因为它必须符合类的规格说明 —— 这是对类的功能、其副作用、哪些状态是有效和无效的、不可变量、前置条件、后置条件等 等的一种非正式的松散描述( 由规格说明给出的对象状态约束只应用于外部可见的状态,即那 些可以通过调用其公共方法和访问其公共字段看到的状态,而不应用于其私有字段中表示的 内部状态)[1] 。 类要成为线程安全的,首先必须在单线程环境中有正确的行为。如果一个类实现正确(这 是说它符合规格说明的另一种方式) ,那么没有一种对这个类的对象的操作序列(读或者写公 共字段以及调用公共方法)可以让对象处于无效状态,观察到对象处于无效状态、或者违反类 的任何不可变量、前置条件或者后置条件的情况。 此外,一个类要成为线程安全的,在被多个线程访问时,不管运行时环境执行这些线程 有什么样的时序安排或者交错,它必须仍然有如上所述的正确行为,并且在调用的代码中没 有任何额外的同步。其效果就是,在所有线程看来,对于线程安全对象的操作是以固定的、 全局一致的顺序发生的。 正确性与线程安全性之间的关系非常类似于在描述 ACID(原子性、一致性、独立性和持 久性)事务时使用的一致性与独立性之间的关系:从特定线程的角度看,由不同线程所执行的 对象操作是先后(虽然顺序不定)而不是并行执行的。 考虑下面的代码片段,它迭代一个 Vector 中的元素。尽管Vector 的所有方法都是同步的, 但是在多线程的环境中不做额外的同步就使用这段代码仍然是不安全的,因为如果另一个线 程 恰 好 在 错 误 的 时 间 里 删 除 了 一 个 元 素 , 则 get() 会 抛 出 一 个 ArrayIndexOutOfBoundsException 。 Vector v = new Vector(); // contains race conditions -- may require external synchronization for (int i=0; iv.size(); i++) { doSomething(v.get(i)); } 这里发生的事情是:get(index) 的规格说明里有一条前置条件要求 index 必须是非负的 并且小

文档评论(0)

kehan123 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档