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

Java 如果所有集合属性都是线程安全的,那么我们可以说这个集合是线程安全的吗?,java,collections,thread-safety,Java,Collections,Thread Safety,如果java集合的所有属性(或项字段或数据成员)都是线程安全的(CopyOnWriteArraySet,ConcurrentHashMap,BlockingQueue,…),我们能说这个集合是线程安全的吗 例如: public class AmIThreadSafe { private CopyOnWriteArraySet thradeSafeAttribute; public void add(Object o) { thradeSafeAttribute

如果java集合的所有属性(或项字段或数据成员)都是线程安全的(
CopyOnWriteArraySet
ConcurrentHashMap
BlockingQueue
,…),我们能说这个集合是线程安全的吗

例如:

public class AmIThreadSafe {

    private CopyOnWriteArraySet thradeSafeAttribute;

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

    public void clear() {
        thradeSafeAttribute.clear();
    }
}
在这个示例中,我们可以说
AmIThreadSafe
线程安全的吗

什么是线程安全?

线程安全仅仅意味着 对象或类的字段始终 保持有效状态,如 其他对象和类,即使在 由多个线程同时使用

线程安全对象是 始终保持有效状态,如 由其他类和对象观察, 即使在多线程环境中


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

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

读到这里,我认为您必须使用上述函数来确保线程安全的集合。但是,您不必对所有集合都使用它们,而且还有更快的线程安全集合,如ConcurrentHashMap。CopyOnWriteArraySet的基本性质确保了线程安全操作。

假设“属性”是指“集合所持有的内容”,那么就不是。仅仅因为
集合
持有线程安全的项目,并不意味着
集合
的实现实现了
添加()
清除()
删除()
,等等。

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

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

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

简短回答:否

回答稍微长一点:因为add()和clear()在任何方面都不同步,而HashSet本身也不同步,所以多个线程可能同时在其中

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

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

在给定的示例中,只支持add()和clear(),这是不可能的

但是在一个更完整的类中,我们将拥有更多的集合接口,想象一个调用方需要向集合中添加一个条目,如果集合中已经没有超过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(AmIThreadSafe集合、对象o、整数限制){
如果(set.size()
问题是,虽然每个调用本身都是线程安全的,但两个线程可能处于AddifyNotOverlimit(或者通过另一个方法添加),因此线程A将调用size()并获取99,然后调用add(),但在此之前,它可能会被中断,线程B可以添加一个条目,而现在这一套就超过了它的极限


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

“根据API文档,您必须使用此函数来确保线程安全”这不一定正确。您还可以简单地使用一个已经线程安全的集合—synchronizedCollection(collection)只是提供了一个方便的包装器。您不必使用它。您可以将它用于非线程安全的集合,如HashMap。但是现在,您可能会使用一个新集合,例如ConcurrentHashMap,它会更快。。。将使用这些线程安全的项目!!所以,我认为我的假设是错误的。“java集合的所有属性”是什么意思?你是说像add()方法这样的“操作”吗?我很确定他指的是操作——属性实际上指的是变量,这些变量几乎总是内部的,在内置集合中甚至是不可访问的。属性是表示对象状态的类和实例变量。。。虽然方法代表了他的行为…所以,错了,你是在问“如果集合的所有操作都是线程安全的,那么我们可以说这个集合是线程安全的吗?”…你完全正确。。。我更新了我的示例,使其与这个问题更加相关……即使使用了“Add”和“Clear”,如果两个方法同时执行,并且每个方法的目的都是让一个集合包含一些精确的项集,独立于它以前的内容(这不是一个罕见的场景),“线程安全”集合不足以确保两个方法运行后,集合将保存第一个方法或第二个方法的精确项集。除非集合以静默方式丢弃重复项,否则即使两个方法都希望安装同一组项,它也不会工作。此外,类中的行为/方法/操作可以以非线程安全的方式对单个线程安全属性进行操作(例如,对于某些类型的“线程安全”对象,例如同步地图,在没有覆盖锁的情况下进行交互)。