3

I faced the following question during an interview:

Lets assume a simple class

public class Example{

   private int a;

   public void update(){

      a = some new value;
   }

   public int getA(){

      return a;
   }

}

Now there are 2 threads (T1 and T2) which read and update the a value in the following sequence:

T2 (call update() and the value was set to 1)
T1 (call getA())
T2 (call update() and the value was set to 2)
T1 (call getA())

Is it possible for the last call getA() of thread T1 to return the value 1? If yes under what circumstances?

7
  • 1
    OK, interesting question. From my cursory knowledge, here, the result could be either 0, 1 or 2. Since no monitor is held between updates and retrievals, there is no happens-before relationship and as such, the result is undefined behavior. Somehow, I'm sure I'm wrong. Commented Feb 19, 2016 at 23:17
  • That's clearly a visibility problem. As stated here. As @fge stated, there's no guarantee of the happens-beforerelationship. Commented Feb 19, 2016 at 23:20
  • @aribeiro volatile cannot be used. The guy said it has to do with L1, L2, L3 caches of the processor but I cant see the relation. Commented Feb 19, 2016 at 23:25
  • Put simply, yes, if T1 calls getA between the two updates called by T2. There's no guarantee as to what order T1 and T2 are interleaved in Commented Feb 19, 2016 at 23:26
  • 2
    Even "the guy" is wrong. Sure, you can investigate at length using dedicated tools etc, but basically the behavior here really is undefined. In fact, my hunch was, I believe, correct. Commented Feb 19, 2016 at 23:27

1 Answer 1

2

The last call to to T1 could return 0, 1, or 2. It doesn't really make sense to ask "under what circumstances." Under the circumstance of running this code, basically. The code isn't written for concurrency, so there's no guarantee.

In to guarantee that a a write to a variable by one thread is visible to a read of that variable by another thread, there needs to be a synchronization point between the threads. Otherwise, the JVM is allowed to optimize things in such a way that changes are only visible to the thread that makes them. For example, the writing thread's current notion of the value can be cached on the processor and written to main memory later or never. When another thread reads main memory for the value, it finds the initial value (0), a stale update (1), or the latest update (2).

The easiest fix in this case would be to declare a as a volatile variable. You'd still need some mechanism to ensure that T2 writes before T1 reads, but only in a weak, wall-clock sense.

Sign up to request clarification or add additional context in comments.

6 Comments

in case only update() is synchronized could that situation still occur?
@eldjon Yes, if only update is synchronized, the reading thread doesn't cross a memory barrier, and can read stale values (a value that it cached from a previous read). If you use synchronized, both the read and the write have to synchronize on the same lock.
so if we used synchronized on update() it wouldn't get 0 right?
what im trying to ask is why would it make a difference if we used synchronized on update() only. the read thread still may not see the changes of the write thread.
@eldjon To put my previous comment more simply, if you only synchronize in update(), it will still be broken. You could still read 0, 1, or 2. I'm not sure how you concluded that, " it wouldn't get 0 right?" after reading my previous comment, but that conclusion was wrong. To work properly, getA() would need synchronization too.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.