用读写锁包装Map

ReadWriteMap使用了ReentrantReadWriteLock来包装Map,使得它能够在多线程间被安全的共享,并仍然能够避免“读-写”或者“写-写”冲突。现实中,ConcurentHashMap的性能已经足够好了(经查看源代码,里面的是每个hash计算后的散列区域作为锁,这个大大减少了锁之间的竞争),

ConcurrentHashMap源码:

public V get(Object key) {
     int hash = hash(key.hashCode());
     return segmentFor(hash).get(key, hash);//使用该hash的对象调用get方法,也就是意为着该对象就是锁
}
final Segment<K,V> segmentFor(int hash) {
        return segments[(hash >>> segmentShift) & segmentMask];
}
V get(Object key, int hash) {
            if (count != 0) { // read-volatile
                HashEntry<K,V> e = getFirst(hash);
                while (e != null) {
                    if (e.hash == hash && key.equals(e.key)) {
                        V v = e.value;
                        if (v != null)
                            return v;
                        return readValueUnderLock(e); // recheck
                    }
                    e = e.next;
                }
            }
            return null;
        }
V readValueUnderLock(HashEntry<K,V> e) {
     lock();//锁便是hash对象
      try {
          return e.value;
      } finally {
          unlock();
      }
  }

所以你可以使用它,而不必使用新的解决方案,如果你需要并发的部分只有部分哈希map,但是如果你需要为LinkedHashMap这种可替换元素的Map提供更多的并发访问,那么这项技术是非常有用的。

import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteMap <K,V> {
	private final Map<K,V> map;
	private final ReadWriteLock lock = new ReentrantReadWriteLock();
	private final Lock r = lock.readLock();
	private final Lock w = lock.writeLock();
	
	public ReadWriteMap(Map<K, V> map){
		this.map = map;
	}
	
	public void put(K key, V value){
		w.lock();
		try{
			return map.put(key, value);
		}finally{
			w.unlock();
		}
	}//remove(), putAll(), clear()也完全类似
	
	public V get(Object key){
		r.lock();
		try{
			return map.get(key);
		}finally{
			r.unlock();
		}
	}//对于其他的只读Map方法也完全类似
}


### 回答1: 一种可行的解决方式是使用ConcurrentHashMap,它是一种特殊的HashMap,它允许多个线程对Map进行访问,同时保证线程安全。它使用分离锁(separate locking)技术来提高性能,可以有效地提高并发访问的性能。 ### 回答2: 在需要线程安全的情况下,考虑到性能问题,可以采用以下方式解决: 1. 使用ConcurrentHashMap:ConcurrentHashMap是一种支持线程安全的哈希表实现。与HashMap不同的是,ConcurrentHashMap使用了分段锁(Segment)来控制并发访问,即多个线程可以同时进行读操作,但写操作会被分段锁所控制,从而提高了并发读的性能。 2. 使用Collections.synchronizedMap:通过将HashMap转换为线程安全的哈希表,可以使用Collections.synchronizedMap方法进行包装。该方法返回一个线程安全的Map对象,在对Map进行写操作时会进行同步,确保线程安全性。虽然在并发环境下性能不如ConcurrentHashMap,但在某些场景下仍然可以满足需求。 3. 使用读写锁(ReentrantReadWriteLock):通过使用读写锁来控制对HashMap的并发访问。读写锁允许多个线程同时进行读操作,但只允许一个线程进行写操作。通过合理地使用读写锁,可以兼顾线程安全和性能。 4. 使用线程安全的并发容器:除了ConcurrentHashMap之外,还有其他线程安全的并发容器可供选择,如ConcurrentSkipListMap、CopyOnWriteArrayList等。根据具体的业务场景和需求,选择合适的并发容器可以提高性能并保证线程安全。 需要注意的是,虽然上述方法可以提供线程安全的HashMap实现,但在并发环境下仍需注意数据的一致性和并发操作带来的性能问题。在实际应用中,应根据具体情况选择最适合的解决方案,权衡线程安全和性能之间的关系。 ### 回答3: 在需要线程安全的情况下,考虑到性能的解决方式可以使用ConcurrentHashMap。 ConcurrentHashMap是HashMap的线程安全版本,通过使用锁分段技术,将整个HashMap分成多个段(Segment)来进行并发控制。每个段拥有自己的锁,不同的线程可以同时访问不同的段,从而提高并发性能。 使用ConcurrentHashMap相比于同步整个HashMap的方式,可以使多个线程同时进行读操作,从而提高并发访问的效率。但是需要注意的是,写操作仍然需要获取整个ConcurrentHashMap的锁,在写操作频繁的情况下,性能可能会受到影响。 另外,除了使用ConcurrentHashMap之外,还可以使用Collections工具类中的synchronizedMap方法将HashMap转化为线程安全的Map。synchronizedMap使用同步块来实现并发控制,确保线程安全性。虽然synchronizedMap可以满足线程安全的需求,但是在并发访问较大的情况下,性能可能会受到较大的影响。 因此,在需要线程安全且高性能的情况下,可以优先考虑使用ConcurrentHashMap。但是需要根据具体的业务场景和性能要求,综合考虑使用哪种解决方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值