同步容器即让线程通过互斥的方式来访问的容器,另一种是并发容器(后面文章会介绍)。互斥锁可以通过synchronized或lock来实现,本文接上文详解java多线程之synchronized,以保持内容的连贯性。
java中的同步容器有Vector, Stack, Hashtable, Collections.synchronizedXXX等包装对象,虽然现在已经很少使用,但面试中可能会遇到。
3.4.1 Vector
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
protected Object[] elementData;
protected int elementCount;
protected int capacityIncrement;
// 继承自AbstractList
protected transient int modCount = 0;
}
-
使用synchronized修饰增删改查方法来同步,同步的是Vector对象
public synchronized boolean add(E e) {...} public boolean remove(Object o) {...} public synchronized E set(int index, E element) {...} public synchronized E get(int index) {...} ...
-
每次修改modCount++, 在迭代,排序...时检查如果modCount变了,抛出
ConcurrentModificationException
@Override public synchronized void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final int expectedModCount = modCount; @SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData; final int elementCount = this.elementCount; for (int i=0; modCount == expectedModCount && i < elementCount; i++) { action.accept(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }
@Override public synchronized void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, elementCount, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }
3.4.2 Stack
继承自Vector,原理一直,不在赘述
- 使用synchronized修饰增删改查方法来同步,同步的是Vector对象
- 每次修改modCount++, 在迭代,排序...时检查如果modCount变了,抛出
ConcurrentModificationException
3.4.3 Hashtable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable {
private transient Entry<?,?>[] table;
private transient int count;
private int threshold;
// default to 0.75f
private float loadFactor;
private transient int modCount = 0;
private static class Entry<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Entry<K,V> next;
}
}
- 使用synchronized修饰增删改查方法来同步,同步的是Vector对象
- 每次修改modCount++, 在迭代,排序...时检查如果modCount变了,抛出
ConcurrentModificationException
3.4.4 Collections.synchronizedXXX
包装原list,set,map,通过synchronized(mutex)代码块同步,mutex默认为当前对象.
比如:
static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
final List<E> list;
public void add(int index, E element) {
synchronized (mutex) {
list.add(index, element);
}
}
}
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
final Collection<E> c; // Backing Collection
final Object mutex;
}