Java 如果所有集合属性都是线程安全的,那么我们可以说这个集合是线程安全的吗?
如果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
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”,如果两个方法同时执行,并且每个方法的目的都是让一个集合包含一些精确的项集,独立于它以前的内容(这不是一个罕见的场景),“线程安全”集合不足以确保两个方法运行后,集合将保存第一个方法或第二个方法的精确项集。除非集合以静默方式丢弃重复项,否则即使两个方法都希望安装同一组项,它也不会工作。此外,类中的行为/方法/操作可以以非线程安全的方式对单个线程安全属性进行操作(例如,对于某些类型的“线程安全”对象,例如同步地图,在没有覆盖锁的情况下进行交互)。