线程安全集合类
古老的
HashTable
Vector
这两个都是古老的线程安全集合类,每个方法上都是用synchronized进行修饰的
并发度很低,并且当多个方法复合执行的时候还是会存在线程安全问题
修饰的
装饰器模式
通过Collections的 synchronized线程不安全的集合 这个方法,可以给我们返回一个线程安全的集合
例如:
/** * Returns a synchronized (thread-safe) map backed by the specified * map. In order to guarantee serial access, it is critical that * <strong>all</strong> access to the backing map is accomplished * through the returned map.<p> * * It is imperative that the user manually synchronize on the returned * map when iterating over any of its collection views: * <pre> * Map m = Collections.synchronizedMap(new HashMap()); * ... * Set s = m.keySet(); // Needn't be in synchronized block * ... * synchronized (m) { // Synchronizing on m, not s! * Iterator i = s.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); * } * </pre> * Failure to follow this advice may result in non-deterministic behavior. * * <p>The returned map will be serializable if the specified map is * serializable. * * @param <K> the class of the map keys * @param <V> the class of the map values * @param m the map to be "wrapped" in a synchronized map. * @return a synchronized view of the specified map. */ public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { return new SynchronizedMap<>(m); } //这个方法就是传过来一个Map线程非安全的集合,返回给我们一个被SynchronizedMap修饰的线程安全的集合
而synchronizedMap的实现方法,其实就是对Map进行了一层封装,比如调用Put方法还是调用我们传过来的线程不安全的Map的方法,但是他们帮我们通过synchronized进行了封装,从而实现了线程安全
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();} } //就比如调用size()方法,还是非线程安全的方法,只不过JDK帮我们加上了同步锁 //...... }
·JUC安全集合·
Blocking
基于锁实现,提供阻塞的方法(take,put)
CopyOnWrite
适合读多写少,当对变量修改的时候会在原值的基础上进行复制,而不会对原值本身进行修改
Concurrent
优点
- 内部使用cas优化,可以保证线程安全的前提下提高较高的吞吐量
缺点
-
弱一致性
-
遍历时弱一致性
正常遍历迭代器时当外部对容器进行修改时,使用**fail-fast**机制立即会报错
但是使用了Concurrent的集合即便外部修改依然可以正常遍历旧的值**fail-safe**
-
求大小时弱一致性
-
读取弱一致性
-