Intra-thread coherence

Viewed 115

The code is simple.

// not annotated with volatile
public static int I = 0;

public static int test(){
    I = 1;
    return I;
}

There is a thread that invokes the method test.

Is it possible the method test will return the value '0'?

In other words, the reading of a shared variable maybe not see the modifying by the same thread.


update

The question just very simple, but I make its obscurity, I'm really sorry about it.

The a thread means a single thread.

And the question is duplicated with it.

3 Answers

No, it will be 1 if no other thread is involved but the one that will invoke the method.

chrylis -cautiouslyoptimistic's answer is worth reading for an alternative scenario as well.

Two reasons:

  • I is just altered by its owner, and if the other thread just calls test(), there's no option for it to get a 0 as I's value.
  • The second thread won't read Class.I's value, but the result of the test() method. The assignation I=1 happens before the return so is guaranteed to offer the latest updated value (which has only been updated by the owner, once).

Any answer that does not explain in terms on java language specification is only partially correct, if correct at all.

You need to make a clear distinction between actions that happens within a single thread and are tied together by program order and that in turn creates a happens-before connection, specifically via:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

That rule tells you that if you think about this code in single threaded world, it will always print 1.

And on the other hand, actions that create synchronizes with connections across different threads, and implicitly those create happens-before, via:

If an action x synchronizes-with a following action y, then we also have hb(x, y).

In your case, I is a plain field, as such every operation related to it is a plain store and/or a plain load. Such stores and loads do not created any connections at all according to the JLS. As such some thread that reads I can always read it as 0 if there is a writing thread involved.

Yes, it is possible for the test method to return 0, if another thread writes to i between the assignment and the return statement:

  1. Thread 1: assign i = 1
  2. Thread 2: assign i = 0
  3. Thread 1: return i (sees the 0 that Thread 2 just wrote)

To prevent this, all access to i, reads and writes, would need to be synchronized on the same condition. Making i volatile is not sufficient to prevent threads from taking turns modifying it.

Note that it's not that Thread 1 "does not see" the i = 1 write; that is guaranteed, because all statements logically execute in program order. However, another thread might change the value after that write happens but before Thread 1 reads it.

Related