为何锁定Thread安全集合?

时间:2014-02-01 18:24:26

标签: java collections synchronization

java.util.concurrent提供了许多线程安全的集合,如ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetConcurrentLinkedQueue。这些集合应该通过允许并发访问数据结构的不同部分来最小化争用。

Java还具有同步包装器,允许并发访问非线程安全集合,如HashMapArraylist

Map<KeyType, ValType> m = Collections.synchronizedMap(new HashMap<KeyType, ValType>());

在处理这些线程安全集合时,我们是否还需要执行客户端锁定?特别是,在做一些迭代的事情吗?

 Set<KeyType> s = m.keySet();  
 synchronized(m) {
     for (KeyType k : s)
         foo(k); 
 }

在这种情况下,是否仅为某些类型的操作提供了线程安全性?

有没有办法在不使用同步的情况下提供线程安全的集合?我熟悉volatile关键字,它可能与非原子操作的原始值一起使用。

1 个答案:

答案 0 :(得分:1)

1)是的,您需要在迭代时执行客户端锁定,但大多数其他方法不需要您执行此操作。请参阅Explain synchronization of collections when iterators are used?

2)所以回答你的第二个问题会自动变为肯定。您可以在文档中看到哪些操作是线程安全的(大多数都是)。

3)关于不使用同步的线程安全集合:这听起来可能是一项艰巨的任务,对于开发平台的专业开发团队来说应该很容易。但实际上,在多核环境和积极优化的时代,这是一场噩梦。功能之间总是需要权衡(这可能听起来像这个一样简单)和性能(处理器缓存中的同步需要大量时间)。请参考Angelica Langer的video(关于java内存模型)。

希望这有帮助。