[四]并发类容器

JDK5.0后提供了多种并发类的容器来代替同步类容器从而改善系统的性能,同步类容器都是串行的,虽然线程安全,但是严重降低了并发性,在多线程环境时,严重降低了应用程序的吞吐量。

听起来有点官方,举个简单的例子:我们去买票,同步类容器就相当于只开了一个售票窗口,买票的人只能一个个排队买,而并发类容器就相当于开了多个窗口,可以同时购票,售票的速度更快。

一:首先来介绍下并发类容器中的ConcurrentMap接口下两个重要的实现:

1:ConcurrentHashMap:

  此并发类容器内部使用segment(段)来将容器分为不同的部分,每一个部分相当于一个小的HashTable,最多分16个段

  

  比如当线程T1对第一小段中的A对象操作(删,改,增)时,线程T2可以同时对第二段中的C对象进行操作。

  相当于是一种减小锁的粒度来达到并发的方案。怎么理解这句话? 原来的同步类容器HashTable,整个对象就一把锁,并发环境下,都要去竞争锁,拿到CPU执行资格才能进行操作。

  而ConcurrentHashMap将容器分为多个小段,也就有了多把锁(最多16把锁),T1跟T2操作的是不同的段,没有锁竞争的关系,所以能够并发执行,在并发操作时底层大量使用volatile关键字,从而第一时间得到修改后的值。

  当然,如果T1跟T2都操作的是第一段中的对象,那么还是会被阻塞等待。

2:ConcurrentSkipListMap:

  相当于以前用的同步类容器中的TreeMap,此类容器弥补了ConcurrentHashMap不能排序的问题。

二:Copy-On-Write 容器:

1:  CopyOnWriteArrayList:

  写时复制,当线程操作(增、删、改)此容器的时候,CopyOnWriteArrayList容器会复制出一个副本,增删改都是操作的这个副本,当操作完成时,容器的引用会指向新的副本所在内存中的地址。

  

     S是CopyOnWriteArrayList的引用,当线程T1操作CopyOnWriteArrayList的引用(简称COW),COW会复制出一个副本集(包含原数据集的所有内容),T1的操作都是基于副本的,对原COW没影响

   当T1操作完成时候,S的引用指向了副本,然后S指向原COW的引用(红叉)被废除,等待垃圾回收器回收。

   当T1在操作(增删改)COW时,此时T2线程进来读取原容器的数据,二者互不干扰,可以并发进行,但是如果T2线程是对COW做写的操作,那么会被阻塞,直至T1执行完成,T2才能继续操作。

   COW适合应用于读多写少的情况下使用。原因:读取不受线程数量的影响。多线程情况下,如果COW内容很多,那么每次写都要复制原容器,比较耗时。

原文地址:https://www.cnblogs.com/wangfajun/p/7145362.html