Cheetah
Cheetah

Reputation: 14419

Thread visibility of an array value change

Lets say I have the following class:

private final int[] ints = new int[5];

public void set(int index, int value) {
    ints[index] = value;
}

public int get(int index) {
    return ints[index]
}

Thread A runs the following:

set(1, 100);

(very) shortly after Thread B runs the following:

get(1)

My understanding is that there is no guarantee that Thread B will see the change that Thread A has been as the change could still be sitting in a CPU cache/register...or there could be instruction reordering...is this correct?

Moving further on, what happens if I have the following class:

public class ImmutableArray {

    public final int[] ints

    public ImmutableArray(int[] ints) {
        this.ints = ints
    }
}

With the following local variable:

volatile ImmutableArray arr;

and Thread A runs the following:

int[] ints = new int[5];
int[0] = 1;

arr = new ImmutableArray(ints);

(very) shortly after Thread B runs the following:

int i = arr.ints[0];

is Thread B guaranteed to get the value 1 because of the final and happens-before relationship, even despite the fact the value in the array was set outside of this?

EDIT: In the second example, the array is never changes, hence the name "ImmutableArray"

Second EDIT::

So what I understand by the answer is that given this:

int a = 0
volatile int b = 0;

If Thread A does the following:

a = 1;
b = 1;

Then the Thread B did the following:

a == 1; // true
b == 1; // true

So volatile acts as a sort of barrier, but at what point does the barrier end and allow reordering of instructions again?

Upvotes: 2

Views: 767

Answers (1)

Marko Topolnik
Marko Topolnik

Reputation: 200236

You are correct on both counts. In fact, you would be right even if you relaxed your problem statement.

In the first example, no matter how much later thread B evaluates get(1), there will be no guarantee that it will ever observe the value written by thread A's call to set(1, 100).

In the second example, either final on the ints or volatile on the arr would be enough on its own for you to have the guarantee of observing ints[0] = 5. Without volatile you wouldn't be guaranteed to ever observe the ImmutableArray instance itself, but whenever you would observe it, you would be guaranteed to observe it in the fully constructed state. More specifically, the guarantee pertains to the complete state reachable from the object's final field as of the moment when the constructor returns.

Upvotes: 2

Related Questions