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!

2 Comments
http://www.visi.com/~khuber/mtrace.log.html
http://www.sonic.net/~gafter/j2se1.5/api/java/util/concurrent/atomic/AtomicLong.html