Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a Java synchronized block, are writes visible on all fields or just the synchronized variable?

Say you have this code:

private String cachedToken;
private final Object lockObject = new Object();

....


retrieveToken(){
 synchronized(lockObject){
  if (cachedToken == null){
   cachedToken = goGetNewToken();
  }
  return cachedToken;
 }
}

Will the write to cachedToken be visible to all threads that have locked on lockObject?

like image 365
Jonathan S. Fisher Avatar asked May 20 '13 15:05

Jonathan S. Fisher


People also ask

How does synchronized block work in Java?

A Synchronized block is a piece of code that can be used to perform synchronization on any specific resource of the method. A Synchronized block is used to lock an object for any shared resource and the scope of a synchronized block is smaller than the synchronized method.

How does synchronized method work in Java?

Java Synchronized Method If we use the Synchronized keywords in any method then that method is Synchronized Method. It is used to lock an object for any shared resources. The object gets the lock when the synchronized method is called. The lock won't be released until the thread completes its function.

Can synchronized method be private?

Putting code in a private method invites letting it be called by other methods, so it would make sense to make the private method synchronized in case in the future it is called from another method that does not otherwise need to be synchronized.

What is difference between synchronized and synchronized block?

Key DifferencesA synchronized method assigns an object-level or class-level corresponding lock. And synchronized block assign a lock to the object based on the parameter.


1 Answers

Yes. Synchronizing on lockObject establishes a Happens Before Relationship (aka sets up a memory barrier). This means that all threads that subsequently get the lock will see any changes that happened while the lock was held previously.

For what it's worth, though, your implementation of lazy initialization is flawed. This is the proper way:

private volatile String cachedToken;

retrieveToken() {
    if (cachedToken == null) {
        synchronized(lockObject) {
            if (cachedToken == null) {
                cachedToken = goGetNewToken();
            }
        }
    }
    return cachedToken
}

This way you only have to get the lock a small handful of times when Threads first start requesting it. After that the cachedToken will not be null, and you won't need to synchronize.

like image 190
Tom McIntyre Avatar answered Oct 13 '22 00:10

Tom McIntyre