Roman
Roman

Reputation: 8231

Caching of instances

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

Upvotes: 2

Views: 487

Answers (3)

Peter
Peter

Reputation: 6362

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.

Upvotes: 1

Sbodd
Sbodd

Reputation: 11454

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.

Upvotes: 2

skaffman
skaffman

Reputation: 403501

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.

Upvotes: 1

Related Questions