ITEEDU

Java Gossip: 容器类的执行绪安全(Thread-safe)

容器类预设没有考虑执行绪安全问题,您必须自行实作同步以确保共享数据在多执行绪存取下不会出错,例如若您使用 List对象时,您可以这样实作:

// arraylist参考至一个ArrayList的一个实例 
synchronized(arraylist) {
	arraylist.add(new SomeClass()); 
}

事实上,您也可以使用Collections的synchronizedXXX()等方法来传回一个同步化的容器对象,例如传回一个同步化的List:

List list = Collections.synchronizedList(new ArrayList());

以这种方式返回的List对象,在存取数据时,会进行同步化的工作,不过在您使用Iterator遍访对象时,您仍必须实作同步化,因为这样的List使用iterator()方法返回的Iterator对象,并没有保证执行绪安全(Thread-safe),一个实作遍访的例子如下:

List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); 
while (i.hasNext())
foo(i.next());
}

在J2SE 5.0之后,新增了 java.util.concurrent 这个 package,当中包括了一些确保执行绪安全的 Collection 类,例如 ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet等等,这些新增的 Collection 类基本行为与先前介绍的Map、List、Set等对象是相同的,所不同的是增加了同步化的功能,而且依对象的特性不同而有不同的同步化实作,以确保效率与安全性。

例如ConcurrentHashMap,它针对Hash Table中不同的区段(segment)进行同步化,而不是对整个对象进行同步化,预设上HashMap有16个区段,当有执行绪在存取第一个区段时, 第一个区域进入同步化,然而另一个执行绪仍可以存取第一个区段以外的区段,而不用等待第一个执行绪存取完成,所以与同步化整个对象来说,新增的这些同步化 对象,在效率与安全性上取得了较好的平衡。