简体   繁体   中英

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 ?

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.

Of course, synchronize ensure two things:

  • Atomicity
  • Memory barrier (what you expect in your case) on the entire object

Whereas for instance, volatile ensure memory barrier but doesn't handle atomicity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM