深入 Java 底层:内存屏障与 JVM并发详解 (1)
2010-04-27 09:17 Dennis Byrne infoQ 我要评论 (0) 字号:
T
|
T
本文介绍了内存屏障对多线程程序的影响, 同时将研究内存屏障与 JVM并发机制的关系, 如
易变量( volatile )、同步( synchronized )和原子条件式( atomic conditional )。
AD:
内存屏障, 又称内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。 本文
假定读者已经充分掌握了相关概念和 Java 内存模型 ,不讨论并发互斥、 并行机制和原子性。
内存屏障用来实现并发编程中称为可见性( visibility )的同样重要的作用。
关于 JVM更多内容,请参阅: JVM详解 Java 虚拟机原理与优化
内存屏障为何重要?
对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存( caching )能够
从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操 作的顺序。也就是
说,程序的读写操作不一定会按照它要求处理器的顺序执行。当数据是不可变的,同时 / 或
者数据限制在线程范围内,这些优化是无害的。
如果把这些优化与对称多处理 (symmetric multi-processing )和共享可变状态 (shared
mutable state )结合,那么就是一场噩梦。当基于共享可变状态的内存操作被重新排序时,
程序可能行为不定。一个线程写入的数据可能被其他线程可见,原因是数据 写入的顺序不
一致。适当的放置内存屏障通过强制处理器顺序执行待定的内存操作来避免这个问题。
内存屏障的协调作用
内存屏障不直接由 JVM暴露,相反它们被 JVM插入到指令序列中以维持语言层并发原语
的语义。 我们研究几个简单 Java 程序的源代码和汇编指令。 首先快速看一下 Dekker 算法中
的内存屏障。该算法利用 volatile 变量协调两个线程之间的共享资源访问。
请不要关注该算法的出色细节。 哪些部分是相关的?每个线程通过发信号试图进入代码
第一行的关键区域。 如果线程在第三行意识到冲突 (两个线程都要访问),通 过 turn 变量
的操作来解决。在任何时刻只有一个线程可以访问关键区域。
1. // code run by first thread // code run by second thread
2.
3. 1 intentFirst = true ; intentSecond = true ;