问题描述
原始java原始整数(int)是什么原因?有两个线程共享一个int的实验似乎表明它们是,但当然没有证据证明它们不并不意味着它们是。
Are java primitive integers (int) atomic at all, for that matter? Some experimentation with two threads sharing an int seems to indicate that they are, but of course absence of evidence that they are not does not imply that they are.
具体来说,我运行的测试是:
Specifically, the test I ran was this:
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。 32位Windows PC上的0_07)
(and that was only tried with java jre 1.6.0_07 on a 32bit windows PC)
本质上,修饰符将计数序列写入共享整数,而观察者检查观察值是否永远不会减少。在必须以四个独立字节(或甚至两个16位字)访问32位值的机器上,观察者有可能在不一致的半更新状态下捕获共享整数,并检测到值减小而不是增加。无论(假设的)数据字节是收集/写入LSB 1st还是MSB 1st,这都应该有效,但最多只能是概率。
Essentially, the Modifier writes a count sequence to the shared integer, while the Watcher checks that the observed values never decrease. On a machine where a 32 bit value had to be accessed as four separate bytes (or even two 16bit words), there would be a probability that Watcher would catch the shared integer in an inconsistent, half-updated state, and detect the value decreasing rather than increasing. This should work whether the (hypothetical) data bytes are collected/written LSB 1st or MSB 1st, but is only probablistic at best.
考虑到今天这个问题很可能即使java规范不需要它,32位值可能是有效原子的数据路径。事实上,使用32位数据总线,您似乎可能需要更加努力地获得字节的原子访问而不是32位整数。
It would seem very probable given today's wide data paths that a 32 bit value could be effectively atomic, even if the java spec doesn't require it. In fact, with a 32 bit data bus it would seem that you might have to work harder to get atomic access to bytes than to 32 bit ints.
谷歌搜索java原始线程安全会在线程安全的类和对象上显示大量内容,但是查找基元的信息似乎是在大海捞针中寻找谚语。
Googling on "java primitive thread safety" turns up loads of stuff on thread-safe classes and objects, but looking for the info on the primitives seems to be looking for the proverbial needle in a haystack.
推荐答案
默认情况下,Java中的所有内存访问都是原子的,但 long
和<$除外c $ c> double (可能是原子的,但不一定是)。说实话并不清楚非常,但我相信这就是含义。
All memory accesses in Java are atomic by default, with the exception of long
and double
(which may be atomic, but don't have to be). It's not put very clearly to be honest, but I believe that's the implication.
来自:
然后在:
请注意,原子性与波动性非常不同。
Note that atomicity is very different to volatility though.
当一个线程将整数更新为5时,保证另一个线程不会看到1或4或者任何其他中间状态,但没有任何明显的波动或锁定,另一个线程可以永远看到0。
When one thread updates an integer to 5, it's guaranteed that another thread won't see 1 or 4 or any other in-between state, but without any explicit volatility or locking, the other thread could see 0 forever.
关于努力获得对字节的原子访问你是对的:VM可能不得不努力......但确实如此。来自的spec:
With regard to working hard to get atomic access to bytes, you're right: the VM may well have to try hard... but it does have to. From section 17.6 of the spec:
换句话说,由JVM决定是否正确。
In other words, it's up to the JVM to get it right.
这篇关于java原始设计或意外原子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!