java双重检查锁定延迟初始化我需要为映射使用volatile关键字吗
从Usage_in_Java & Effective Java 2开始,我知道如果惰性初始化目标是单个变量,我需要volatile
关键字
但是,我要执行多个延迟初始化,并将它们存储在ConcurrentHashMap
中,怎么样?这个Map
也需要易变吗
下面是代码示例
public class Utils {
private static final Map<Integer, RemoteViews> remoteViewsMap = new ConcurrentHashMap<Integer, RemoteViews>();
public static RemoteViews getRemoteViews(int resourceId) {
RemoteViews remoteViews = remoteViewsMap.get(resourceId);
if (remoteViews == null) {
synchronized(remoteViewsMap){
remoteViews = remoteViewsMap.get(resourceId);
if (remoteViews == null) {
remoteViews = new RemoteViews("org.yccheok.gui", resourceId);
remoteViewsMap.put(resourceId, remoteViews);
}
}
}
return remoteViews;
}
}
上述代码正确且线程安全吗
# 1 楼答案
不需要
volatile
关键字,因为ConcurrentHashMap
作为ConcurrentMap
的实现提供了以下内存一致性效果:然而,这不是您通常希望使用并发映射的方式。一般情况如下:
注意,它不能防止两个线程同时调用
new Object()
(如果创建新对象的成本很高,这可能是一个问题),但它允许您一起避免显式同步更新:对于双重检查锁定,在您的情况下,应该如下所示: