List实现线程安全,在java中我找到自带有两种方法,一种是通过Collections.synchronizedList()方法,另一种是copyonwriteArrayList代替ArrayList;
Collections方法的实现
从Collections源码中,我们可以看出,Collections.synchronizedList实现线程安全的方法是使用synchronized实现,
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
CopyOnWriteArrayList方法实现
CopyOnWriteArrayList是写时复制,他通过ReentrantLock 实现加锁,并且在写入数据前都会复制原数组,写入数据成功后在将旧的数组替换掉,get()是无锁的。
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//复制数据
Object[] newElements = Arrays.copyOf(elements, len + 1);
//为数组添加新元素
newElements[len] = e;
//替换成新数组
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
总结
从源码可以看出,Collections方法实现的线程安全是通过synchronized 关键字,而CopyOnWriteArrayList时使用ReentrantLock 加锁,但CopyOnWriteArrayList每次添加数据时,都会复制一份数组,因此,Collections方法实现的同步方法在添加元素(调用add方法)的效率要高于CopyOnWriteArrayList,Collections方法实现的get()方法同样也是加锁的,而CopyOnWriteArrayList的get()方法无锁,因此CopyOnWriteArrayList的get()方法效率更高,由此,Collections方法更适用于插入频繁的时候,而CopyOnWriteArrayList更适用于查询频繁的时候。