您的位置:首页 > 编程语言 > Java开发

Java并发:线程安全的容器:同步和并发

2016-03-31 22:20 736 查看
转载请注明出处:jiq•钦's technical Blog - 季义钦

1. 引言
多线程环境正确发布共享数据的方法之一就是线程安全容器。
线程安全的容器是由锁保护的域,将数据放入线程安全的容器中,可以保障其被安全地发布给所有从这个容器访问它的线程。

2. 同步容器类

JDK1.0开始有两个很老的同步容器类:Vector和HashTable。
JDK1.2之后Collections工具类中添加了一些工厂方法返回类似的同步封装器类:
public static <T> Collection<T>synchronizedCollection(Collection<T> c)
static<T> List<T> synchronizedList(List<T> list) //包装ArrayList、LinkedList
static<T> Set<T> synchronizedSet(Set<T> s)  //包装HashSet
static<K,V> Map<K,V> synchronizedMap(Map<K,V> m) //包装HashMap
static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T>s) //包装TreeSet
static <K,V> SortedMap<K,V>synchronizedSortedMap(SortedMap<K,V> m) //包装TreeMap
 
实现方式:
将它们的状态封装起来,并对每一个公有方法进行同步。
其中Vector就是Object[]+synchronized方法,Hashtable是HashtableEntry[]+synchronized方法。而synchronizedXXX()方法返回的同步封装器类更是简单地将传进来的Collection的所有方法封装为synchronized方法而已。
 
缺点:
1、  通过同步方法将访问操作串行化,导致并发环境下效率低下
2、  复合操作(迭代、条件运算如没有则添加等)非线程安全,需要客户端代码来实现加锁。

3. 并发容器类

并发容器出现的最大的需求就是提升同步容器类的性能!
可以对比(非并发容器类)看看,将单线程版本和并发版本做一个比较。

1、HashMap和HashSet的并发版本

1.1 ConcurrentHashMap<K, V>(HashMap的并发版本)
版本:JDK5
目标:代替Hashtable、synchronizedMap,支持复合操作
原理:采用一种更加细粒度的加锁机制“分段锁”,任意数量读取线程可以并发读取,任意数量的读取线程和一个写线程可以并发访问,一定数量的写入线程可以并发访问。并发环境下ConcurrentHashMap带来了更高的吞吐量,而在单线程环境下只损失了很小的性能。
 
1.2 CopyOnWriteArraySet<E>(HashSet的并发版本)
版本:JDK5
目标:代替synchronizedSet
原理:CopyOnWriteArraySet基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。

2、TreeMap和TreeSet的并发版本

2.1 ConcurrentSkipListMap<K, V>(TreeMap的并发版本)
版本:JDK6
目标:代替synchronizedSortedMap(TreeMap)
原理:Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,通过"空间来换取时间"的一个算法。ConcurrentSkipListMap提供了一种线程安全的并发访问的排序映射表。内部是SkipList(跳表)结构实现,在理论上能够在O(log(n))时间内完成查找、插入、删除操作。
 
2.2 ConcurrentSkipListSet<E>(TreeSet的并发版本)
版本:JDK6
目标:代替synchronizedSortedSet
原理:内部基于ConcurrentSkipListMap实现!
 

3、ArrayList和LinkedList的并发版本

3.1 CopyOnWriteArrayList<E>(ArrayList的并发版本)
目标:代替Vector、synchronizedList
原理:CopyOnWriteArrayList的核心思想是利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。
 
3.2 ConcurrentLinkedQueue<E>(LinkedList的并发版本)
目标:代替Vector、synchronizedList
特点:基于链表实现的FIFO队列,特别注意单线程环境中LinkedList除了可以用作链表,也可用作队列,并发版本也一样
        

4、阻塞队列:BlockingQueue

版本:JDK1.5
特点:拓展了Queue,增加了可阻塞的插入和获取等操作
实现类
LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列
ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列
PriorityBlockingQueue:按优先级排序的队列
原理:通过ReentrantLock实现线程安全,通过Condition实现阻塞和唤醒。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: