这个线程在java中是安全和高效的吗
} 在上面的代码中,在放置和删除时,使用readLock而不是writeLock,它们是最常用的。在打开和关闭时,都使用writeLock,它们的使用频率较低。目标是提高并发性。我不确定: 它是线程安全的吗? 效率高吗? 我认为两者都是肯定的。我知道ConcurrentHashMap是线程安全的。我想知道这个实现是好是坏以及原因。线程安全: 从某种意义上说,它是线程安全的。调用close后,进一步调用put和remove不会影响concurrentHashMap引用的映射的状态 但是,在下次打开之前调用put和remove将导致更新丢失。这给我的印象是糟糕的设计。。。考虑到开放和关闭的表面目的是避免丢失更新。这可能是另一个级别的线程安全问题 效率: 一方面:我观察到所有地图更新都是在您持有锁的情况下执行的。鉴于此,我认为使用ConcurrentHashMap没有任何意义。使用常规HashMap将是线程安全和更高效的 另一方面,由于所有更新都是在持有锁的情况下执行的,因此锁是一个并发瓶颈,使用ConcurrentHashMap的潜在并发优势是没有意义的 我想我应该使用原子引用来实现它。。。没有锁。诀窍是使用ref.getAndSetnew ConcurrentHashMap将现有映射切换为新的空映射 原子引用仍然是一个并发瓶颈,但程度要小得多,而且您可以避免关闭。。。通过将两个动作作为单个原子操作来打开孔这个线程在java中是安全和高效的吗,java,multithreading,concurrency,thread-safety,concurrenthashmap,Java,Multithreading,Concurrency,Thread Safety,Concurrenthashmap,} 在上面的代码中,在放置和删除时,使用readLock而不是writeLock,它们是最常用的。在打开和关闭时,都使用writeLock,它们的使用频率较低。目标是提高并发性。我不确定: 它是线程安全的吗? 效率高吗? 我认为两者都是肯定的。我知道ConcurrentHashMap是线程安全的。我想知道这个实现是好是坏以及原因。线程安全: 从某种意义上说,它是线程安全的。调用close后,进一步调用put和remove不会影响concurrentHashMap引用的映射的状态 但是,在下次打开
有关使用原子引用的示例解决方案,请参见@Holger的答案。。。注意到他的版本没有提到结尾。。。裸眼问题。正如其他人所说,通过使用此用例的原子参考,可以提高效率。但是,也许更重要的是,代码变得更简单:
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;
}
ConcurrentHashMap的实现是线程安全和并发的。为什么不让map本身成为最终的呢?为什么要处理它为空?实现似乎没有添加任何内容,现在每个putIfAbsent和remove都有全局锁,而直接使用CHM时没有全局锁,所以我认为实现是不好的。实现提供的一件事是原子清晰,我认为CHM没有。如果这很重要,也许考虑一下AtomicReference。也可以是无锁的。@KhalidShah,锁的作用是保护map变量,而不是保护map的内容。如果没有锁定,不同的线程可能会在哪个ConcurrentHashMap实例是当前实例的问题上产生分歧。1。有了锁,我想不能使用HashMap,因为多线程会调用put方法。2.使用AtomicReference,无法将现有映射切换为新的空映射,因为当调用close方法时,在有人调用open之前,没有人可以再调用put。3.使用AtomicReference,您无法在关闭时安全地处理旧数据,因为当您迭代旧映射时,另一个线程可能会获得旧映射引用,并将数据放入旧映射。如果有其他线程使用映射而未使用打开和关闭或获取锁,则您的应用程序不是线程安全的。如果你想准确回答你的问题,你应该包括所有相关的代码。请编辑您的问题以添加其他线程如何访问/迭代/更新映射的示例。您无法在close中正确处理旧数据,因为当线程A迭代器关闭旧映射时,线程B in put可能获得旧映射引用,并且正在将数据放入旧映射。这样,线程B的新put数据可能不会在线程A的关闭迭代器中接触。如果您是对的,当前映射与null的原子交换并不排除线程已经拥有映射。这可以用一个AtomicStampedReference来修复,它维护正在进行的更新的数量,但是这与使用ReentrantReadWriteLock没有太大区别。
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;
}