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

时间:2013-05-20 15:45:48

标签: java concurrency synchronization

说你有这段代码:

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

....


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

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

2 个答案:

答案 0 :(得分:10)

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

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

private volatile String cachedToken;

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

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

答案 1 :(得分:7)

当然,synchronize确保了两件事:

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

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