[英]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.