是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();
}
}
(这只是尝试与java jre 1.6.0_07在32位Windows PC上)
基本上,修改器将计数序列写入共享整数,而观察者检查观察值从不减小。在一个32位值必须作为四个独立字节(或甚至两个16位字)访问的机器上,将有一个概率,Watcher将捕获处于不一致,半更新状态的共享整数,并检测值减少而不是增加。这应该工作是否(假设)数据字节收集/写入LSB第一或MSB第一,但只是最大概率。
在今天的宽数据路径中,32位值可能是有效原子的,即使java规范不需要它,似乎非常可能。事实上,使用32位数据总线,似乎你可能不得不更努力地获取字节的原子访问而不是32位的int。
在“java原语线程安全性”上搜索会导致线程安全类和对象上的东西的负载,但寻找原语上的信息似乎在寻找在大海捞针的谚语针。