views:

122

answers:

3

Hi all

I am just curious about the java memory model a little.

Here is what i though.

If i have the following class

public class Test {

    int[] numbers = new int[Integer.MAX_VALUE]; // kids dont try this at home

    void increment(int ind){
        numbers[ind]++;
    }

    int get(int ind){
        return numbers[ind];
    }
}

There are multiple readers get() and one writer increment() thread accessing this class.

The question is here , is there actually any synchronization at all that i have to do in order to leave the class at a consistent state after each method call?

Why i am asking this, i am curious if the elements in the array are cached in some way by the JVM or is this only applied to class members? If the members inside the array could be cached, is there a way to define them as volatile ?

Thanks Roman

+1  A: 

Yes, the VM is allowed to cache inside the thread any field that is not synchronized or voltile. To prevent this, you could mark the fields as volatile, but they still wouldn't be thread safe, since ++ is not an atomic operation. Add the synchronized keyword to the methods, and you're safe.

skaffman
+2  A: 

As an alternative to synchronizing those methods, you could also consider replacing the int[] with an array of AtomicIntegers. This would have the benefit/downside (depending on your application) of allowing concurrent access to different elements in your list.

Sbodd
And it's also 10 times faster than using synchronized.
starblue
@starblue: I suppose you have benchmarks to back up that rather bold claim? It's be astonished if it was any faster at all, unless the thread contention was extremely high.
skaffman
well in that case starblue is right , since synchronizing the methods of this class would lock the whole array.And still it is more desirable to use a single CAS operation where you can fit it , instead of synchronizing on something
Roman
+1  A: 

You will definitely have to use some sort of synchronization (either on your class or the underlying data structure) in order to ensure the data is left in a consistent state after method calls. Consider the following situations, with two Threads A and B, with the integer array initially containing all zero values.

  • Thread A calls increment(0). The post-increment operation is not atomic; you can actually consider it to be broken down into at least three steps:
    • Read the current value; Add one to the current value; Store the value.
  • Thread B also calls increment(0). If this happens soon after Thread A has done the same, they will both read the same initial value for the element at index 0 of the array.
  • At this point, both Thread A and B have read a value of '0' for the element they want to increment. Both will increment the value to '1' and store it back in the first element of the array.
  • Thus, only the work of the Thread that last writes to the array is seen.

The situation is similar if you had a decrement() method. If both increment() and decrement() were called at near-simultaneous times by two separate Threads, there is no telling what the outcome would be. The value would either be incremented by one or decremented by one, and the operations would not "cancel" each other out.

EDIT: Update to reflect Roman's (OP) comment below

Sorry, I mis-read the post. I think I understand your question, which is along the lines of:

"If I declare an array as volatile, does that mean access to its elements are treated as volatile as well?"

The quick answer is No: Please see this article for more information; the information in the previous answers here is also correct.

Peter
You have probably missed the point that this is accessed by multiple readers and one writer. MRSWIn case of multiple writers you are absolutely right.Still no one is giving me the answer to my question if the array values are volatile or not .. :-)
Roman
Sorry about the misunderstand, I've updated my post with a better answer.
Peter
Thanks for the link, i know this site. Must have overseen it there :-)Seems the array elements could be cached.
Roman