如果所有集合属性都是线程安全的,那么我们可以说这个集合是线程安全的吗?

时间:2009-12-21 17:55:29

标签: java collections thread-safety

如果java集合的所有属性(或项目字段或数据成员)都是线程安全的CopyOnWriteArraySetConcurrentHashMapBlockingQueue ,. ..),我们可以说这个集合是线程安全的吗?

一个例子:

public class AmIThreadSafe {

    private CopyOnWriteArraySet thradeSafeAttribute;

    public void add(Object o) {
        thradeSafeAttribute.add(o);
    }

    public void clear() {
        thradeSafeAttribute.clear();
    }
}

在此示例中我们可以说AmIThreadSafe 线程安全吗?

4 个答案:

答案 0 :(得分:3)

假设“属性”是指“收集的内容”,则不是。仅仅因为Collection包含线程安全的项目并不意味着Collection的实现实现了add()clear()remove()等等。线程安全的方式。

答案 1 :(得分:2)

不,因为对象的状态是其所有属性的“总和”。

例如,您可以在对象中使用2个线程安全集合作为属性。此外,您的对象可能依赖于这两个集合之间的某种关联(例如,如果一个对象在一个集合中,它在另一个集合中,反之亦然)。简单地使用2个线程安全的集合将无法确保在所有时间点都存在相关性。您需要在对象中使用其他并发控制,以确保此约束在两个集合中保持不变。

由于大多数非平凡对象在其属性中具有某种类型的关联关系,因此使用线程安全集合作为属性不足以使对象成为线程安全的。

答案 2 :(得分:2)

简答:否

稍微长一点的答案:因为add()和clear()没有以任何方式同步,并且HashSet本身不同步,所以多个线程可能同时存在于其中。

编辑以下评论:啊。现在简短的回答是是,sorta 。 :)

“sorta”(美国俚语,部分意思是顺便说一句)的原因是两个操作可能是原子安全的,但是当组合使用以进行复合操作时是不安全的。

在您给出的示例中,只支持add()和clear(),这不可能发生。

但是在一个更完整的类中,我们将拥有更多的Collection接口,想象一个调用者需要在集合中添加一个条目,如果该集合已经不超过100个条目。

这个调用者想要写一个像这样的方法:


void addIfNotOverLimit (AmIThreadSafe set, Object o, int limit) {
   if (set.size() < limit)      // ## thread-safe call 1
      set.add(o);               // ## thread-safe call 2
}
问题是虽然每个调用本身都是线程安全的,但是两个线程可以在addIfNotOverLimit中(或者就此而言,通过另一个方法完全添加),所以线程A会调用size()并得到99,然后调用add (),但在此之前,它可能会被中断,然后线程B可以添加一个条目,现在该集合将超过其限制。

道德?复合操作使“线程安全”的定义更加复杂

答案 3 :(得分:1)

  

什么是线程安全?

     

线程安全只是意味着   对象或类的字段总是如此   保持有效状态,如所观察到的那样   其他对象和类,即使是   由多个线程同时使用。

     

一个线程安全的对象就是那个   始终保持有效状态,如   通过其他类和对象观察,   即使在多线程环境中也是如此。

根据API文档,您必须使用此功能来确保线程安全:

synchronizedCollection(Collection c) 
         Returns a synchronized (thread-safe) collection 
         backed by the specified collection

读到这一点,我认为你必须使用上面的函数来确保线程安全的Collection。但是,您不必将它们用于所有集合,并且有更快的集合,这些集合是线程安全的,例如ConcurrentHashMap。 CopyOnWriteArraySet的基本特性可确保线程安全操作。