[英]Is this thread safe and efficient in java
public class Test {
static ConcurrentHashMap<Integer, Integer> map = null;
final static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static void open() {
lock.writeLock().lock();
try {
if (map != null) {
return;
}
map = new ConcurrentHashMap<>();
} finally {
lock.writeLock().unlock();
}
}
public static void close() {
final ConcurrentHashMap<Integer, Integer> concurrentHashMap;
lock.writeLock().lock();
try {
if (map == null) {
return;
}
concurrentHashMap = map;
map = null;
} finally {
lock.writeLock().unlock();
}
// deal with concurrentHashMap data
}
public static boolean put(final int key, final int value) {
lock.readLock().lock();
try {
if (map == null) {
return false;
}
if (map.putIfAbsent(key, value) != null) {
return false;
}
} finally {
lock.readLock().unlock();
}
return true;
}
public static boolean remove(final int key) {
lock.readLock().lock();
try {
if (map == null) {
return false;
}
if (map.remove(key) == null) {
return false;
}
} finally {
lock.readLock().unlock();
}
return true;
}
}
在上面的代碼中,當put()和remove()時,使用readLock而不是writeLock,它們是最常用的;當open()和close()時,它們都使用writeLock,它們的使用率較低。 目標是提高並發性。 我不確定:
我認為兩者都是。 我知道ConcurrentHashMap是線程安全的。 我想知道此實現的好壞,為什么。
從某種意義上說,它是線程安全的。 調用close
之后,進一步的put
和remove
調用將不會影響concurrentHashMap
引用的地圖的狀態。
但是,在下一次open
之前調用put
和remove
將導致更新丟失。 考慮到open
和close
是避免丟失更新,因此這讓我感到很不滿意。 這可能是另一個級別的線程安全問題。
一方面:我觀察到在您持有鎖的同時對地圖的所有更新都已執行。 鑒於此,我認為使用ConcurrentHashMap
沒有任何意義。 使用常規的HashMap
將是線程安全的,並且效率更高。
另一方面,由於所有更新都是在持有該鎖的同時執行的,因此該鎖是並發瓶頸,使用ConcurrentHashMap
的潛在並發優勢尚無定論。
我想我會使用AtomicReference
( javadoc )...來實現它,並且沒有鎖。 訣竅是使用ref.getAndSet(new ConcurrentHashMap())
將現有地圖“切換”為新的空地圖。
AtomicReference
仍將是並發瓶頸,但程度要小得多,並且可以通過將這兩個操作作為單個原子操作進行操作來避免“關閉...打開”漏洞。
有關使用AtomicReference
的示例解決方案,請參見@Holger的答案...,請注意,他的版本無法解決“封閉...裸眼”問題。
正如其他人所說,可以通過針對此用例使用AtomicReference
來提高效率。 但是,更重要的是,代碼變得更加簡單:
static final AtomicReference<ConcurrentHashMap<Integer, Integer>>
MAP = new AtomicReference<>();
public static void open() {
MAP.compareAndSet(null, new ConcurrentHashMap<>());
}
public static void close() {
ConcurrentHashMap<Integer, Integer> map = MAP.getAndSet(null);
if(map != null) {
// deal with map data
}
}
public static boolean put(final int key, final int value) {
ConcurrentHashMap<Integer, Integer> map = MAP.get();
return map != null && map.putIfAbsent(key, value) == null;
}
public static boolean remove(final int key) {
ConcurrentHashMap<Integer, Integer> map = MAP.get();
return map != null && map.remove(key) != null;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.