单个线程中的静态int比AtomicInteger的计数多,为什么会这样?

时间:2014-02-20 11:09:47

标签: java multithreading thread-safety

以下代码的输出为9123:9158

import java.util.concurrent.atomic.AtomicInteger;

public class StackOverflow {

    private static AtomicInteger atomicInteger = new AtomicInteger(0);
    private static int staticInt = 0;

    public static void main(String args[]) {

        int atomicInt = atomicInteger.incrementAndGet();

        staticInt++;

        try {
            // recursive call to main() to get StackOverflowError
            main(args);

        } catch(StackOverflowError soe) {

            System.out.println(atomicInt+":"+staticInt);
            // staticInt gets more count, why so?
        }
    }
}

这会在static intAtomicInteger之间产生35的差异。我不确定为什么会这样,我有这些问题我想得到答案。

在单个线程上运行时,两者都应该给出相同的计数吗?知道为什么这不是这样吗?

我们如何获得StackOverflowError所需的正确呼叫次数?

AtomicInteger contekt中使用static是否错误?

2 个答案:

答案 0 :(得分:9)

这是因为您正在打印atomicInt。如果您打印atomicInteger,则会获得预期结果。

每次调用atomicInt时都会有一个main变量,所以在您的示例中有9000多个这样的变量。

当你得到StackOverflowError时,执行以相反的顺序通过堆栈直到System.out.println语句可以执行(它也可能抛出一个SOE!),并且atomicInt的值对应于特定main调用小于staticIntatomicInteger的临界值。

换句话说,在您的示例中,抛出了34个StackoverflowError,并且System.out.println的第35次调用成功,但atomicInt调用中的main比当前值小35 staticInt,因此9123 vs 9158。

要查看它,您可以像这样修改您的程序:

private static int soeCount = 0;

//...

} catch (StackOverflowError soe) {
    soeCount++;
    System.out.println(atomicInt + ":" + staticInt + " -> " + soeCount);
    // staticInt gets more count, why so?
}

你应该看到soeCount大于1(虽然不一定等于差异,因为soeCount++可能不会在每个堆栈帧上执行。

答案 1 :(得分:3)

似乎System.out.println(atomicInt+":"+staticInt);也导致堆栈溢出。所以你实际上早先打印了一些化身的值。

staticInt是一个静态字段,因此它具有最大化身数,而atomicIntmain的实体中实际成功执行{{1}的本地变量}}