For the longest time, I’ve been happily deluding myself that the
++ operator is atomic in Java. I tried never to give it
much thought because I wanted it to be atomic.
But those blissful days are over:
In the JVM an increment is not atomic and involves both a read and a write.
(via the latest Java Performance Tuning Newsletter, via via Bruce Eckel.)
Not happy to take anyone’s word for it, I wrote the following bit of
Java to test the various ways1 you can use ++ on an
int. I’ve included the corresponding output of javap after each relevant
statement. As you can see, only the increment of a local variable is implemented
via one JVM opcode (iinc), so it is the only form of ++ increment
that is even potentially atomic2. All the rest do involve a read and a write.
public class Test {
public static int staticInt = 0;
public static int[] staticIntArray = {0};
public int memberInt = 0;
public int[] memberIntArray = {0};
public static void testStaticInt()
{
staticInt++;
/*
0: getstatic #4; //Field staticInt:I
3: iconst_1
4: iadd
5: putstatic #4; //Field staticInt:I
*/
}
public static void testStaticIntArray()
{
staticIntArray[0]++;
/*
0: getstatic #5; //Field staticIntArray:[I
3: iconst_0
4: dup2
5: iaload
6: iconst_1
7: iadd
8: iastore
*/
}
public void testMemberInt()
{
memberInt++;
/*
0: aload_0
1: dup
2: getfield #2; //Field memberInt:I
5: iconst_1
6: iadd
7: putfield #2; //Field memberInt:I
*/
}
public void testMemeberIntArray()
{
memberIntArray[0]++;
/*
0: aload_0
1: getfield #3; //Field memberIntArray:[I
4: iconst_0
5: dup2
6: iaload
7: iconst_1
8: iadd
9: iastore
*/
}
public void testLocalInt()
{
int i = 0;
/*
0: iconst_0
1: istore_1
*/
i++;
/*
2: iinc 1, 1
*/
}
public void testLocalIntArray()
{
int[] ia = {0};
/*
0: iconst_1
1: newarray int
3: dup
4: iconst_0
5: iconst_0
6: iastore
7: astore_1
*/
ia[0]++;
/*
8: aload_1
9: iconst_0
10: dup2
11: iaload
12: iconst_1
13: iadd
14: iastore
*/
}
}
1 All the various types of “l-values”. The JVM accesses local variables, member variables and static variables differently. Also, you can increment a cell in an array, so that’s an “l-value” too.
2 And who cares if a local-variable increment is atomic? It doesn’t matter; it’s a local variable. It can’t be accessed by multiple threads anyway!

3 Comments
http://www.visi.com/~khuber/mtrace.log.html
http://www.sonic.net/~gafter/j2se1.5/api/java/util/concurrent/atomic/AtomicLong.html
I finally managed to observe the lack of atomicity of the ++ operator in the wild today. It’s one of those things you know is not atomic, but is very nearly atomic and you don’t expect your world to come crashing down if you use it. But guess what, your world will come crashing down!
Thanks for this thorough discussion of why it’s not atomic.
Neal, there is also AtomicInteger which would fit better with the examples (as they are all ints).