List线程安全——java技术栈系列文章

IT黑名单 2016-12-14 10:43:39

目录

List线程安全的实现:
1、Vector;
2、CopyOnWriteArrayList
3、Collections.synchronizedList(list)
先说Vector,Vector是一个基于数组实现的线程安全的list,其实现方式是对所有操作都加上synchronized关键字。此种方式严重影响执行效率,不再推荐。
Collections.synchronizedList

public static <T> List<T> synchronizedList(List<T> list) {
	return (list instanceof RandomAccess ?
		new SynchronizedRandomAccessList<>(list) :
		new SynchronizedList<>(list));
}
以上是Collections.synchronizedList的源码,其中SynchronizedRandomAccessList继承自SynchronizedList。
看SynchronizedList源码可知,SynchronizedList部分方法加上了synchronized以保证线程安全,但iterator方法还是不安全的(该方法没有加synchronized),需要用户自己保证同步。

CopyOnWriteArrayList
public E get(int index) {
	return get(getArray(), index);
}

public E set(int index, E element) {
	final ReentrantLock lock = this.lock;
	lock.lock();
	try {
		Object[] elements = getArray();
		E oldValue = get(elements, index);

		if (oldValue != element) {
			int len = elements.length;
			Object[] newElements = Arrays.copyOf(elements, len);
			newElements[index] = element;
			setArray(newElements);
		} else {
			// Not quite a no-op; ensures volatile write semantics
			setArray(elements);
		}
		return oldValue;
	} finally {
		lock.unlock();
	}
}
可以看到,在set方法中先是使用ReentrantLock.lock保证了线程的可见性和顺序性,进而保证线程安全;
然后Arrays.copyOf进行数组复制操作,随后在新数组上作写操作,最后赋值。这样就不会有读写操作作用在同一个数组对象上(写操作操作的是新的数组引用),而读操作不会产生线程安全问题。
查看源码可以知道,add、remove、clear、sort等方法上均如此处理。


两者比较
性能比较的测试代码不再粘贴,有兴趣可以自己动手写一下(最好能自己动手测试一下,有时候博主写的不一定就对,更有时候随着版本变更对的也不再继续对了)。
总的来说,CopyOnWriteArrayList写操作时做了copy,读写分离保证了读的高性能,适用于读远大于写的场景;
Collections.synchronizedList适合读写均匀或者写大于读的场景。


转载请注明来源【IT黑名单

本文链接:http://blog.itblacklist.cn/20161214/8440.html

© Copyright 2016 IT黑名单 Inc.All Rights Reserved. 豫ICP备15018592号-2