Home > Net >  Do we need to make a field 'volatile', if Thread1 enters sync block, updates it, is still
Do we need to make a field 'volatile', if Thread1 enters sync block, updates it, is still

Time:07-20

Let's say we have 'class A' which has a data member 'var'.

class A
{
  int var;

method()
{
read(var);

synchronized block
{

update var here;

}

}

Let's say Thread 1 acquires the lock and enters the synchronized block. It updates the field value 'var'. Let's say the field value is cached in the processor's core by the Thread. It updates the value in the cache.

Now thread 2 starts running, enters method(), and reads field value 'var'.

Wil thread 2, surely get the updated value? Does synchronize makes sure thread 2 will get updated value even when Thread 1 has not exited Synchronized. In this case, do we need to make 'var' volatile?

PS - Everything is happening on the same object.

CodePudding user response:

If you would not make 'var' volatile, then there is no happens-before edge between writing and reading 'var'. So you have a data race on your hands and weird things can happen like the compiler messing things up.

So in short: make it volatile (or make sure you read 'var' using the same lock).

CodePudding user response:

Does synchronize makes sure thread 2 will get updated value

No. synchronized doesn't do anything for a thread if the thread does not enter a synchronized block. The way to think about synchronized is this: Whatever one thread does before it leaves a synchronized block is guaranteed to become visible to some other thread by the time the second thread subsequently* enters a block that is synchronized on the same lock object.

For a single int variable, you could make it volatile instead. volatile makes a guarantee similar to the guarantee of synchronized: Whatever one thread does before it updates a volatile variable is guaranteed to become visible to some other thread by the time the second thread subsequently* reads the same volatile variable.


* Edit: I added "subsequently" to make it clear that neither synchronized nor volatile is sufficient to ensure that the threads will access var in some particular order. If you wish to ensure that thread 2 will not try to read var until after thread 1 has assigned it, then you will have to use some other means† to coordinate their activity. Correct use of synchronized or volatile only can ensure that IF thread 1 updates var before thread 2 examines it, then thread 2 will see the update.

† There are many "other means." One example is a Semaphore. Thread 1 could release() a permit to the semaphore after it updates var, and thread 2 could acquire() the permit before it reads var. The acquire() call would cause thread 2 to wait if it arrived at the semaphore before thread 1 had done its job.

  • Related