如何将一个类改造为线程安全-例如TreeMap

对这个问题,好多人可能第一反应就是使用syschronized关键字,诚然应用这个关键字可以解决问题(仍是有条件线程安全的且低效的),

贴上Collections.synchronizedMap(new TreeMap<>()) 源码:

  public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }

    /**
     * @serial include
     */
    private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;

        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize

        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }

        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }


通过最后两行代码,可以看到Collections.synchronizedMap的线程安全实质上是在get,put方法加上了独占锁,不仅put存的时候加锁,取得时候也加了锁,所以性能比较差。


但是在无意中看java源码时,看到了另一种更高效的方式—采用lock的方式,使用读写锁。

在ReentrantReadWriteLock的源码注释中,作者写了这样一段代码:

class RWDictionary {

     private final Map<String, Data>  m = new TreeMap<String, Data>();

     private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

     private final Lock r = rwl.readLock();

     private final Lock w = rwl.writeLock();

 

     public Data get(String key) {

         r.lock(); try { return m.get(key); } finally { r.unlock(); }

     }

     public String[] allKeys() {

         r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }

     }

     public Data put(String key, Data value) {

         w.lock(); try { return m.put(key, value); } finally { w.unlock(); }

     }

     public void clear() {

         w.lock(); try { m.clear(); } finally { w.unlock(); }

     }

  }


这段代码同样实现了对TreeMap本来非线程安全的类,包装成了一个线程安全的类,且不存在Collections.SynchronizedMap的put_if_absent问题。


ref:

https://www.cnblogs.com/weiwelcome0/archive/2012/05/25/2518558.html

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值