Java并发编程实践-教程-05章.pdf
文本预览下载声明
第 1 页 共 32 页
第5章 数据冲突及诊断工具MTRAT
第 5 章 数据冲突及诊断工具MTRAT1
5.1 如何避免数据冲突2
5.1.1 数据冲突与竞争条件2
5.1.2 锁与数据冲突4
5.1.3 采用原子性操作避免数据冲突9
5.1.4 采用Volatile避免数据冲突11
5.1.5ThreadLocal 14
5.2 使用阻塞队列的生产者-消费者模式15
5.3 MTRAT介绍19
5.3.1 有潜在数据冲突的例子20
5.3.2 MTRAT软件介绍22
5.3.3 Mtrat软件测试案例25
5.3.4 Mtrat软件的其他选项27
5.4 使用MTRAT诊断数据冲突28
参考文献:32
Linux公社(LinuxIDC.com) 是包括Ubuntu,Fedora,SUSE技术,最新IT资讯等Linux专业类网站。
第 2 页 共 32 页
在前面的章节中,我们已经了解了线程安全和数据冲突的概念,在本章中我们将讲解
如何避免数据冲突,以及如何进行诊断。由于并行程序的不确定性造成并行程序的错误很难
查找,重现和调试,IBM 提供的 MTRAT 工具 可以收集程序的运行时信息,实时分析程序
中所有可能的并行程序错误(如死锁、数据冲突) 。
5.1 如何避免数据冲突
在前面的章节中我们已经了解了数据冲突。当线程之间共享数据引起了并发执行程序
中的同步问题就是数据冲突。
Java 的数据有两种基本类型内存分配模式(不算虚拟机内部类型,详细内容参见虚拟
机规范):运行时栈和堆两种。由于运行时栈是线程所私有的,它主要用来保存局部变量和
中间运算结果,因此它们的数据是不可能被线程之间所共享的。内存堆是创建类对象和数组
地方,它们是被虚拟机内各个线程所共享的,因此如果一个线程能获得某个堆对象的引用,
那么就称这个对象是对该线程可见的。
编写线程安全的代码,本质上就是管理对状态(state )的访问,而且通常这些状态都是
共享的、可变的。一个对象的状态就是它的数据,存储在状态变量(state variables )中,比
如实例域或静态域。对象的状态还包括了其他附属对象的域。
例如,在 Web 网站中,我们为统计系统的点击数设计了一个计数器。由于计数器是被
多用户共享的,每个用户访问时都涉及“读-改-写”等操作,由于这些操作都不是原子的,
计数器有可能出现问题。
两个线程在缺乏同步的条件下,试图同时更新一个计数器时。假设计数器的初始值为
19,在某些特殊的分时里,每个线程都将读它的值,并看到值是 19,然后同时加 1,最后
都将 counter 设置为 20。很显然,这不是我们期望发生的事情:一次递增操作凭空取消了,
一次命中计数被永久地取消了。在基于 Web 的服务中,如果计数器出现这种问题,可能问
题不大,但已经导致严重的数据完整性问题和错误。如各在其他环境中,如银行帐号管理,
那就不可原谅。
在并发编程环境中,这种问题有一个专用的名称叫竞争条件。
5.1.1
显示全部