JUC-java并发编程-并发工具类- 线程安全的集合类(1)

7 篇文章 0 订阅
6 篇文章 0 订阅

JUC

线程安全的集合类

在这里插入图片描述

线程安全集合列可以分为三大类:

1.遗留的线程安全集合类:Hashtable,Vector

Hashtable(Since: JDK1.0)中的所有方法都是加了synchronized的锁(并发度很低)。

public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
        throw new NullPointerException();
    }

    // Makes sure the key is not already in the hashtable.
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K,V> entry = (Entry<K,V>)tab[index];
    for(; entry != null ; entry = entry.next) {
        if ((entry.hash == hash) && entry.key.equals(key)) {
            V old = entry.value;
            entry.value = value;
            return old;
        }
    }

    addEntry(hash, key, value, index);
    return null;
}

2.使用Collections装饰的线程安全集合,如:

  • Collections.synchronizedCollection
  • Collections.synchronizedList
  • Collections.synchronizedMap
  • Collections.synchronizedSet
  • Collections.synchronizedNavigableMap
  • Collections.synchronizedNavigableSet
  • Collections.synchronizedSortedMap
  • Collections.synchronizedSortedSet

使用Collections类的方法装饰,是利用装饰器模式,通过一个Collections的内部同步类装饰所需要操作的容器,以synchronizedMap(Map<k,v> m)为例,返回的是SynchronizedMap对象(SynchronizedMap实现了Map接口),SynchronizedMap对象有一个final Object mutex;//Object on which to synchronize 属性,该属性为同步锁,还有一个属性为private final Map<K,V> m;//Backing Map,该属性为所需要同步的容器。synchronizedMap对map的所有方法重新,在调用所有方法上都使用synchronized(mutex)加锁。

总结,所以Collections类的装饰也是在每个方法的调用加了synchronized锁(并发度依旧不高)

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
    return new SynchronizedMap<>(m);
}
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);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }
    ...
}

3.java.util.concunrrent.*

重点介绍java.util.concurrent.*下的线程安全集合类,可以发现他们有桂略,里面包含三类关键词:Blocking、CopyOnWrite、Concurrent

  • Blocking大部分实现基于锁,并提供用来阻塞的方法

  • CopyOnWrite之类容器修改开销相对较重(适用于读多写少的场景,修改的开销相对较重)

  • Concurrent类型的容器

    • 内部很多操作使用cas优化,一般可以提供较高吞吐量

    • 弱一致性

      • 遍历时弱一致性,例如,当利用迭代器遍历时,如果容器发生修改,迭代器仍然可以继续进行遍历,这是内容是旧的
      • 求大小弱一致性,size操作未必是100%准确的
      • 读取弱一致性

      遍历时如果发生了修改,对于非安全容器来讲,使用fail-fast机制也就是让遍历立即失败,抛出ConcurrentModificationException,不再继续遍历。

      对于线程安全的容器,并发情况下遍历不会失败,采用的机制是fail-safe。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值