Jus*_*eff 41 java multithreading
那个java原始整数(int)是原子的吗?两个共享一个int的线程的一些实验似乎表明它们是,但当然没有证据表明它们不是并不暗示它们是.
具体来说,我跑的测试是这样的:
public class IntSafeChecker {
static int thing;
static boolean keepWatching = true;
// Watcher just looks for monotonically increasing values
static class Watcher extends Thread {
public void run() {
boolean hasBefore = false;
int thingBefore = 0;
while( keepWatching ) {
// observe the shared int
int thingNow = thing;
// fake the 1st value to keep test happy
if( hasBefore == false ) {
thingBefore = thingNow;
hasBefore = true;
}
// check for decreases (due to partially written values)
if( thingNow < thingBefore ) {
System.err.println("MAJOR TROUBLE!");
}
thingBefore = thingNow;
}
}
}
// Modifier just counts the shared int up to 1 billion
static class Modifier extends Thread {
public void run() {
int what = 0;
for(int i = 0; i < 1000000000; ++i) {
what += 1;
thing = what;
}
// kill the watcher when done
keepWatching = false;
}
}
public static void main(String[] args) {
Modifier m = new Modifier();
Watcher w = new Watcher();
m.start();
w.start();
}
}
Run Code Online (Sandbox Code Playgroud)
(这只是在32位Windows PC上尝试使用java jre 1.6.0_07)
实质上,Modifier将计数序列写入共享整数,而Watcher检查观察值是否永远不会减少.上的机器,其中一个32位的值有四个独立的字节(或甚至两个16位字)将被访问,将有一个概率观察者会赶上在不一致的,半更新的状态的共享整数,并且检测值减少而不是增加.无论(假设的)数据字节是收集/写入LSB 1st还是MSB 1st,这都应该有效,但最多只能是概率.
考虑到今天的宽数据路径,即使java规范不需要它,32位值也可能是有效的原子,这似乎是非常可能的.实际上,使用32位数据总线,您可能需要更加努力地获得对字节的原子访问而不是32位整数.
谷歌搜索"java原始线程安全"会在线程安全的类和对象上显示大量内容,但是查找基元上的信息似乎是在大海捞针中寻找谚语.
Jon*_*eet 60
Java中的所有内存访问都是原子的,除了long
和double
(可能是原子的,但不一定是).说实话并不是很清楚,但我相信这就是含义.
从JLS 第17.4.3节开始:
在顺序一致的执行中,对于与程序的顺序一致的所有单个动作(例如读取和写入)存在总顺序,并且每个单独的动作是原子的并且对于每个线程立即可见.
然后在17.7:
一些实现可能发现将64位长或双值上的单个写操作划分为相邻32位值上的两个写操作是方便的.为了效率,这种行为是特定于实现的; Java虚拟机可以原子地或分两部分对long和double值执行写入.
请注意,原子性与波动性非常不同.
当一个线程将一个整数更新为5时,它保证另一个线程不会看到1或4或任何其他中间状态,但没有任何明显的波动或锁定,另一个线程可以永远看到0.
关于努力获得字节的原子访问,你是对的:VM可能必须努力......但它确实必须这样做.从规范的第17.6节:
某些处理器不提供写入单个字节的能力.通过简单地读取整个字,更新适当的字节,然后将整个字写回存储器,在这样的处理器上实现字节数组更新是违法的.这个问题有时被称为单词撕裂,并且在处理器上无法轻易地单独更新单个字节,将需要一些其他方法.
换句话说,由JVM决定是否正确.
归档时间: |
|
查看次数: |
19876 次 |
最近记录: |