参考https://blog.csdn.net/wandou9527/article/details/108224511
如何避免并发问题
(1)使用Vector
(2)使用Collections.synchronizedList()
Collections.synchronizedList()对ArrayList对象进行包装
List<Integer> arraylist = Collections.synchronizedList(new ArrayList());
源码:
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
newSynchronizedRandomAccessList<T>(list) :
new SynchronizedList<T>(list));
}
上述类的继承结构如上所示,SynchronizedList是SynchronizedRandomAccessList的父类,我们现在看下SynchronizedList的源码,了解下为什么SynchronizedList是线程安全的。
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public boolean equals(Object o) {
synchronized(mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized(mutex) {return list.hashCode();}
}
public E get(int index) {
synchronized(mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized(mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized(mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized(mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized(mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized(mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection<? extends E> c) {
synchronized(mutex) {return list.addAll(index, c);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
public ListIterator<E> listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
}
public List<E> subList(int fromIndex, int toIndex) {
synchronized(mutex) {
return new SynchronizedList<E>(list.subList(fromIndex, toIndex),
mutex);
}
}
/**
* SynchronizedRandomAccessList instances are serialized as
* SynchronizedList instances to allow them to be deserialized
* in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
* This method inverts the transformation. As a beneficial
* side-effect, it also grafts the RandomAccess marker onto
* SynchronizedList instances that were serialized in pre-1.4 JREs.
*
* Note: Unfortunately, SynchronizedRandomAccessList instances
* serialized in 1.4.1 and deserialized in 1.4 will become
* SynchronizedList instances, as this method was missing in 1.4.
*/
private Object readResolve() {
return (list instanceof RandomAccess
? new SynchronizedRandomAccessList<E>(list)
: this);
}
}
关于mutex定义:
final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize
SynchronizedCollection(Collection<E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
mutex = this;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = c;
this.mutex = mutex;
}
易知,mutex指向的就是当前对象自己,所以SynchronizedList是线程安全的根本原因是使用Synchronized对SynchronizedList的add,delete等操作进行加锁,但是这种锁的力度很大,所以这种方式效率低下。
(3)使用CopyOnWriteArrayList
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
源码:
private static final long serialVersionUID = 8673264195747942595L;
/** The lock protecting all mutators */
transient final ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private volatile transient Object[] array;
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
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();
}
}
从add方法知道:CopyOnWriteArrayList底层数组的扩容方式是一个一个地增加,而且每次把原来的元素通过Arrays.copy()方法copy到新数组中,然后在尾部加上新元素e.它的底层并发安全的保证是通过ReentrantLock进行保证的,CopyOnWriteArrayList和SynchronizedList的底层实现方式是不一样的,前者是通过Lock机制进行加锁,而后者是通过Synchronized进行加锁,至于两者的区别,下次详细描述。