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