volatile Array is a volatile reference to an array, not a reference to an array of volatile elements! html
I get asked a lot about how the volatile keyword interacts with arrays, so it is probably worth a blog post on the subject.
Those of you who have read my posts on volatile (Volatile Fields and Synchronization, Volatile Does Not Mean Atomic and, most importantly, What Volatile Means in Java) will have a pretty good idea of what volatile means, but it is probably worth it to provide a reminder.
Basically, if you write to a volatile field, and then you have a later read that sees that write, then the actions that happened before that write are guaranteed to be ordered before and visible to the actions that happen after the read. In practice, what this means is that the compiler and the processor can't do any sneaky reordering to move actions that come before the write to after it, or actions that come after the write to before it. See my post on What Volatile Means in Java for more detail.
With that out of the way, let's go through some examples of what you can do with volatile arrays: java
volatile int [] arr = new int[SIZE]; arr = arr; int x = arr[0]; arr[0] = 1;The first lesson to learn, which will guide us here, is that arr is a volatile reference to an array, not a reference to an array of volatile elements! As a result, the write to arr[0] is not a volatile write. If you write to arr[0] , you will get none of the ordering or visibility guarantees that you want from a volatile write.
arr = arrThis one is easy. The volatile read is on the right hand side of the assignment statement.
int x = arr[0];This one is slightly more subtle. The volatile read is not the read of the array element. The right hand side of that assignment is a two step process. First, you read the array reference, then you read the 0th element of that array. The volatile read is the read of the array reference, not the read of the 0th element.
arr[0] = 1;The previous example should give you a hint of where the volatile read is on this line. As in that example, the left-hand side is a two step process. First, you read the array reference, then you assign to the 0th element of that array. As odd as it seems, the read of the array reference is a volatile read .
// I wouldn't do this if I were you. volatile int [] arr = new int[SIZE]; arr[0] = 1; arr = arr;This definitely does provide the volatile write. However, what good does it do you? The virtue of a volatile write is that a corresponding read can detect that it happened, and do something based on the new value. For example, you can use a volatile flag to force one thread to loop indefinitely until another one sets the flag. In this case, you can't actually detect that another thread performed the write, because it is writing the same value to the variable.
Don't despair too much, though — Doug Lea and the clever folks involved in JSR-166 are working on better solutions for Java 7. More news as events warrant. app
A slight complication of Java volatile fields, and one sometimes overlooked, is that declaring an array volatile does not give volatile access to its fields!. At least, it doesn't when elements of the array are accessed with "normal" Java syntax. In other words: less
So, what do we do if we want a truly volatile array in Java, where the array's individual fields have volatile semantics? ide
The AtomicIntegerArray class implements an int array whose individual fields can be accessed with volatile semantics, via the class's get() and set() methods. Calling arr.set(x, y) from one thread will then guarantee that another thread callingarr.get(x) will read the value y (until another value is read to position x). oop
This is slightly kludgy and slightly inefficient (since what would be one write now involves two writes) but I believe it is theoretically correct. After setting an element of the array, we re-set the array reference to be itself: post
volatile int[] arr = new int[...]; ... arr[4] = 100; arr = arr;
The marginal benefit of this technique could be: ui