当多线程并发访问一个 List 的实例时,可以使用 Collections.synchronizedList(List<T>)
将 List 的实例进行包装,其内部调用的构造函数位于 Collections.java at jdk8-b120:
1 | static class SynchronizedCollection<E> implements Collection<E>, Serializable { |
可以看出内部使用了 mutex
作为锁的对象以保证线程安全,而为什么不直接在方法上加上 synchronized
以实现相同的语义呢?是因为第二个构造函数允许用户传入锁的对象,比如用户需要使用单个锁来同步多个集合时,以实现对多集合多线程的并发访问。
在 Collections.synchronizedList(List<T>)
方法的 Java Doc 中还提到,使用迭代器时需要在外部加锁。
It is imperative that the user manually synchronize on the returned list when iterating over it:
1
2
3
4
5
6
7 List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}Failure to follow this advice may result in non-deterministic behavior.
Reference
Why does SynchronizedCollection assign this to a mutex? - Stack Overflow