在Java synchronized块中,是在所有字段上显示还是只在同步变量上写入?

Jon*_*her 11 java concurrency synchronization

说你有这个代码:

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

....


retrieveToken(){
 synchronized(lockObject){
  if (cachedToken == null){
   cachedToken = goGetNewToken();
  }
  return cachedToken;
 }
}
Run Code Online (Sandbox Code Playgroud)

写入对cachedToken锁定的所有线程是否可见lockObject

Tom*_*yre 10

是.在lockObject上进行同步会在关系之前建立一个Happens(也就是设置一个内存屏障).这意味着随后获得锁定的所有线程将看到先前保持锁定时发生的任何更改.

但是,对于它的价值,你的延迟初始化的实现是有缺陷的.这是正确的方法:

private volatile String cachedToken;

retrieveToken() {
    if (cachedToken == null) {
        synchronized(lockObject) {
            if (cachedToken == null) {
                cachedToken = goGetNewToken();
            }
        }
    }
    return cachedToken
}
Run Code Online (Sandbox Code Playgroud)

这样,当线程首次开始请求时,您只需要少量锁定.之后,cachedToken将不为null,您不需要同步.


Mik*_*378 7

当然,要synchronize确保两件事:

  • 原子性
  • 整个对象的内存障碍(在您的情况下您所期望的)

例如,volatile确保内存屏障但不处理原子性.