我只是想探索什么是ThreadSafe意味着什么?
以下是我的理解:
对我而言;允许多个线程同时访问集合;这与其同步无关。例如,没有synchronized关键字的任何方法;是线程安全的,意味着多个线程可以访问它。
开发人员可以选择在此方法上维护更多逻辑(同步),以便在多线程访问数据时保持数据完整性。这与线程安全是分开的。
如果我的上述陈述是假的;只需阅读以下JAVA DOC中的“ConcurrentHashMap:
”keySet:视图的迭代器是一个永远不会抛出的“弱一致”迭代器 ConcurrentModificationException,并保证在构造迭代器时遍历元素,并且可能(但不保证)反映构造之后的任何修改。
上述声明称keySet迭代器不保证数据完整性;多线程正在修改集合。
你能否回答我,* ConcurrentHashMap的KeySet迭代器是线程安全的吗?
我对线程安全的理解是正确的吗?
答案 0 :(得分:3)
java.util.concurrent
包背后的一般想法是提供一组数据结构,这些数据结构提供线程安全访问而没有强大的一致性。这样,这些对象实现了更高的并发性,然后正确锁定了对象。
线程安全意味着,即使没有任何显式同步,也不会破坏对象。在HashTable
和HashMap
中,某些方法是多线程访问的潜在问题,例如remove
方法,它首先检查元素是否存在,然后将其删除。这些方法在ConcurrentHashMap
中实现为原子操作,因此您不必担心会丢失一些数据。
但是,这并不意味着每个操作都会自动锁定此类。诸如putAll
和迭代器之类的高级操作不同步。该课程不具备强大的一致性。保证操作的顺序和时间不会破坏对象,但不能保证生成准确的结果。
例如,如果您通过调用putAll
同时打印对象,则可能会看到部分填充的输出。与新插入同时使用迭代器也可能无法反映所引用的所有插入。
这与线程安全不同。即使结果可能会让您大吃一惊,但您可以放心,不会丢失或意外覆盖任何内容,可以毫无问题地添加和删除元素。如果此行为足以满足您的要求,建议您使用java.util.concurrent
类。如果您需要更多一致性,则需要使用java.util
中的同步类或自己使用同步。
答案 1 :(得分:2)
keySet:视图的迭代器是一个“弱一致”的迭代器,它永远不会抛出ConcurrentModificationException,并保证遍历构造迭代器时存在的元素,并且可能(但不保证)反映构造后的任何修改
这就解释了,ConcurrentHashMap的 KeySet迭代器是线程安全的。
答案 2 :(得分:1)
根据您的定义,Set
返回的ConcurrentHashMap.keySet()
是线程安全的。
然而,正如你所包含的引文中所指出的,它可能以非常奇怪的方式起作用。
Set
,条目可能随机显示和/或消失。即如果您在同一个对象上调用contains
两次,则两个结果可能会有所不同。Iterable
,您可以在两个不同的线程中开始对其底层对象进行两次迭代,并发现两次迭代枚举不同的条目。contains
和迭代可能也不匹配。但是,如果您在保留Map
的同时以某种方式锁定基础Set
,则不会发生此活动,但需要这样做并不意味着结构不是线程安全