1.背景
集合类中的map,大家一定熟悉,知道它非线程安全。使用的方法有两种,一种是在map上加同步器(锁),另一种是创建容器时使用Collections中的静态方法对map进行包装。
java api 中的例子:
1 Map m = Collections.synchronizedMap(new HashMap()); 2 ... 3 Set s = m.keySet(); // Needn't be in synchronized block 4 ... 5 synchronized (m) { // Synchronizing on m, not s! 6 Iterator i = s.iterator(); // Must be in synchronized block 7 while (i.hasNext()) 8 foo(i.next()); 9 } 10
2.疑问
到这里大家可能会有疑问。
第一,既然已经进行了包装,为什么返回的是线程安全的包装类,里面是如何实现的?
第二,这个类是线程安全的,接下来的iterator的使用为什么需要用户进行同步化呢?
我们看Collections.synchronizedMap的源码,
1 。。。 2 public <T> T[] toArray(T[] a) { 3 synchronized (mutex) {return c.toArray(a);} 4 } 5 6 public Iterator<E> iterator() { 7 return c.iterator(); // Must be manually synched by user! 8 } 9 10 public boolean add(E e) { 11 synchronized (mutex) {return c.add(e);} 12 } 13 public boolean remove(Object o) { 14 synchronized (mutex) {return c.remove(o);} 15 } 16 。。。
对于第一个问题,
大部分方法中都已经用synchronized关键字进行修饰了,因此保证了线程安全性。
对于第二个问题,
源码中未进行同步化,需要用户自己对 iterator的调用以及hasNext和Next 进行同步化。HasNext和next方法的调用,源码控制不了,所以用户自己做同步话操作。
个人理解,有不对的地方,望大家指正,共同探讨。