java - Java ConcurrentHashSet - 在多线程环境中对其进行迭代
问题描述
我已经看到了 SynchronizedList 的用例——他们声明在迭代时,即使 SynchronizedList 是线程安全的,我们也应该像这样使用迭代器和同步块——
synchronized(myList){
Iterator<Item> iterator = myList.iterator();
while (iterator.hasNext())
{
System.out.println(iterator.next().getMessage());
}
}
例如,如果我使用 ConcurrentHashSet(可能在 Java 8 中使用 concurrentHashMap 的 newKeySet()),在多线程环境中,是否仍然需要提取迭代器并使用同步块?我尝试对其进行测试,这似乎没有必要,但我可能会遗漏一些东西。
谢谢!
解决方案
ConcurrentHashMap.newKeySet()
返回:
/**
* Creates a new {@link Set} backed by a ConcurrentHashMap
* from the given type to {@code Boolean.TRUE}.
*
* @param <K> the element type of the returned set
* @return the new set
* @since 1.8
*/
public static <K> KeySetView<K,Boolean> newKeySet() {
return new KeySetView<K,Boolean>
(new ConcurrentHashMap<K,Boolean>(), Boolean.TRUE);
}
如您所见,它由 ConcurrentHashMap 支持。您可以使用返回的实例而无需任何同步。
.iterator()
方法返回一个KeyIterator
由地图支持的新的Node<K,V>[] table
因此,如果您在一个特定线程中进行迭代,这意味着您将看到数组的快照,Node
并且每个处于正确状态的节点 bcNode
内部都有易失链接,但是您看到新元素添加到原始地图 bc 链接迭代器点的可能性最低不挥发。换句话说,您只是迭代一个数组,而没有任何保证该元素是否仍然存在于原始地图 atm 中或在那里添加了一些新元素,但是您可以看到每个节点的最新状态,bc:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val;
volatile Node<K,V> next;
key
是最终的
val
易变
推荐阅读
- reactjs - 传播运算符未在 React 中复制结果
- c# - 将生成的 Pdf 作为电子邮件附件发送 Asp.NetCore
- css - VS 代码上的 SCSS 自动建议
- node.js - Discord.js 角色反应
- python - 具有多列且轴 = 0 的 df.apply 示例
- php - 如何使用 Guzzle 通过 POST 请求从 URL 发送文件
- c# - 'Aspnetuserlogins' 需要定义主键(互连数据库)
- c++11 - C++-11 类模板实例化崩溃 gprof ......有什么建议吗?
- libgdx - 如何在不先单击的情况下使 libGDX 滚动窗格滚动
- sql - SQL查询将表分组为表?