[英]Is this the correct and efficient way to make a singleton map thread safe in a static method
我只想在地图初始化时创建一次锁。 这是我正在使用的代码。
public static Map<String, String> getOrderStatusInstance() {
if (orderStatusMap == null) {
synchronized (Utility.class) {
orderStatusMap = new HashMap<String, String>();
orderStatusMap.put("Key1", "Value1");
orderStatusMap.put("Key2", "Value2");
orderStatusMap.put("Key3", "Value3");
orderStatusMap.put("Key4", "Value4");
}
}
return orderStatusMap;
}
不,那是个坏主意-您将返回一个可变的,非线程安全的映射。 您还尝试实现双重检查锁定,但未正确执行-与使用静态初始化相比,要使其正确无误。
我将创建一个不可变的映射(使用Guava作为首选项),理想情况下,应作为类初始化的一部分:
private static final ImmutableMap<String, String> STATUS_MAP = ImmutableMap.of(
"Key1", "Value1",
"Key2", "Value2",
"Key3", "Value3",
"Key4", "Value4");
public static ImmutableMap<String, String> getOrderStatusInstance() {
return STATUS_MAP;
}
(对于超过5个键/值对,请使用ImmutableMap.Builder
。)
您是否真的需要比这更懒惰?
几乎是正确的...考虑一个线程检查orderStatusMap == null并变为true的情况。 然后,调度程序切换到另一个执行相同检查的线程。 没有两个线程都将执行同步块。
通过在同步块中再次检查null来防止这种情况:
if (orderStatusMap == null) {
synchronized (Utility.class) {
if (orderStatusMap == null) {
Map<String, String> tmp = new HashMap<String, String>();
tmp.put("Key1", "Value1");
tmp.put("Key2", "Value2");
tmp.put("Key3", "Value3");
tmp.put("Key4", "Value4");
orderStatusMap = tmp;
}
}
}
return orderStatusMap;
是的,这样做两次就可以了。 外部检查仍然有助于提高性能,因为在创建映射后,无需再执行进入同步块的昂贵步骤。
请记住,这是创建哈希图的线程安全方法。 它不会使映射成为线程安全的。
PS:如果您喜欢这个问题,您可能还会喜欢: 如何直接初始化HashMap(以字面方式)?
您应该再次检查synchronized
块内是否为null
。
当两个线程调用您的方法时,它们都将发现orderStatusMap
为null,其中一个将在synchronized
块内,而另一个将在块内。 但最终它将在同步块内传递并再次初始化映射。
不,这是不正确的
也没有必要在这里进行延迟初始化(我相信无论如何都应该过度使用),所以只需执行以下操作:
private static final Map<String, String> orderStatusMap;
static{
orderStatusMap = Collections.synchronizedMap(new HashMap<String, String>());//making it thread safe
//or use a ConcurrentHashMap
orderStatusMap.put("Key1", "Value1");
orderStatusMap.put("Key2", "Value2");
orderStatusMap.put("Key3", "Value3");
orderStatusMap.put("Key4", "Value4");
}
public static Map<String, String> getOrderStatusInstance() {
return orderStatusMap;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.