什么是并发容器?
因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低了并发性,当多个线程竞争容器时,吞吐量严重降低。
相对同步容器而言,并发容器通过一些机制改进了并发性能。
并发容器类型
ConcurrentHashMap
ConcurrentHashMap 在 JDK7 加锁的时候根据散列值锁住了散列值锁对应的那段,因此提高了并发性能。
当然 ConcurrentHashMap 在 JDK8 以后不在使用分段储存,而是使用类似乐观锁的方式(
CAS + synchronized
)来达到多线程安全的目的。CopyOnWriteArrayList 和 CopyOnWriteArraySet
分别代替 List 和 Set,主要是在遍历操作为主的情况下来代替同步的 List 和同步的 Set,这也就是上面所述的思路:迭代过程要保证不出错,除了加锁,另外一种方法就是”克隆”容器对象。
ConcurrentLinkedQuerue
是一个先进先出的队列。它是非阻塞队列。
ConcurrentSkipListMap
可以在高效并发中替代 SoredMap(例如用 Collections.synchronzedMap 包装的 TreeMap)。
- ConcurrentSkipListSet
可以在高效并发中替代 SoredSet(例如用 Collections.synchronzedSet 包装的 TreeMap)。
CopyOnWrite
- 什么是 CopyOnWrite 容器?
CopyOnWrite 容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行 Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。
这样做的好处是我们可以对 CopyOnWrite 容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以 CopyOnWrite 容器也是一种读写分离的思想,读和写不同的容器。
CopyOnWrite 并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景。
CopyOnWrite 容器存在的问题?
内存占用问题
:因为 CopyOnWrite 的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象。如果这些对象占用的内存比较大,比如说 200M 左右,那么再写入 100M 数据进去,内存就会占用 300M,那么这个时候很有可能造成频繁的 Yong GC 和 Full GC。数据一致性问题
:CopyOnWrite 容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用 CopyOnWrite 容器。