众所周知,常见的容器类(如HashMap和ArrayList )不是线程安全的,但在单线程模型中运行效率更高
以前,java通过锁定实现了两个线程安全的同步容器类: Vector和Hashtable
也可以使用java类库中提供的Collections类的synchronizedXxxx方法为非线程安全容器创建同步容器类
例如:
listwidgetlist=collections.synchronized list (new ArrayList () );
容器类同步问题
容器类同步是线程安全的,但在某些情况下需要客户端锁定以保护复合操作
常见的复合操作包括迭代(遍历容器)
跳(找到下一个元素)
条件运算
同步容器类的所有操作都是线程安全的,但如果其他线程更改容器,上述复合操作将显示意外行为
publicstaticobjectgetlast (向量列表) {
intlastindex=list.size((-1;
返回列表. get (last index;
}
上面的代码非常典型,size和get操作是线程安全的,但是如果其他线程可能删除了list中的元素,最后会抛出ArrayIndexOutOfBoundsException异常
因此,在这种情况下,客户端必须锁定整个表以保护复合操作
迭代器和补偿模型描述元xception
无论是直接使用迭代器执行迭代操作,还是使用for-each循环语法,都使用迭代器对象来实现迭代操作
如果其他线程同时修改容器,则迭代器需要在迭代过程中锁定容器,但jdk设计并未考虑此问题。 在实际环境中,如果容器在迭代期间被其他线程修改,则会抛出concurrentmodificationexception异常
解决此问题的最直观方法是锁定,但锁定意味着多个线程之间的竞争,可能会显著降低吞吐量和CPU利用率。 另一种替代方法是克隆容器并对副本进行迭代,以防止其他线程修改它。 他的主要开销是创建克隆容器的阶段