Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static int is getting more count than AtomicInteger in single thread, why so?

Output of the following code is 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?
        }
    }
}

This produces a difference of 35 between static int and AtomicInteger. I am not sure why this behaves so and I have these questions I would like to get answers for.

While running on a single thread both should give same count right? Any idea why this is not behaving so?

How do we get the correct number of calls required for StackOverflowError to occur?

Is it wrong to use AtomicInteger in a static contekt?

like image 381
WarFox Avatar asked Feb 20 '14 11:02

WarFox


2 Answers

It's because you are printing atomicInt. If you printed atomicInteger instead you would get the expected result.

There is one atomicInt variable per call to main, so in your example there are 9000+ such variables.

When you get the StackOverflowError, the execution goes through the stack in reverse order until the System.out.println statement can execute (it may throw a SOE too!), and the value of the atomicInt corresponding to that specific main invocation is smaller than the curent value of staticInt or atomicInteger.

In other words, in your example, 34 StackoverflowError are thrown and the 35th invocation of System.out.println succeeds, but atomicInt in that invocation of main is 35 less than the current value of staticInt, hence 9123 vs 9158.

To see it you can modify your program like so:

private static int soeCount = 0;

//...

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

and you should see that soeCount is larger than 1 (although not necessarily equal to the difference as soeCount++ may not be executed on each stack frame.

like image 107
assylias Avatar answered Sep 28 '22 20:09

assylias


It seems that System.out.println(atomicInt+":"+staticInt); is also causing a stack overflow. So you actually print the values of a few incarnations earlier.

staticInt is a static field, so it has the max number of incarnations, while atomicInt is a local variable in the incarnation of main that actually succeeds in executing the println.

like image 34
Henry Avatar answered Sep 28 '22 20:09

Henry