Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 最终的不可修改集是线程安全的吗?_Java_Collections_Thread Safety - Fatal编程技术网

Java 最终的不可修改集是线程安全的吗?

Java 最终的不可修改集是线程安全的吗?,java,collections,thread-safety,Java,Collections,Thread Safety,目前还不清楚:不可修改的集合是线程安全的吗?还是应该担心内部状态并发问题 Set<String> originalSet = new HashSet<>(); originalSet.add("Will"); originalSet.add("this"); originalSet.add("be"); originalSet.add("thread"); originalSet.add("safe?"); final Set<String> unmodifi

目前还不清楚:不可修改的集合是线程安全的吗?还是应该担心内部状态并发问题

Set<String> originalSet = new HashSet<>();
originalSet.add("Will");
originalSet.add("this");
originalSet.add("be");
originalSet.add("thread");
originalSet.add("safe?");
final Set<String> unmodifiableSet = Collections.unmodifiableSet(originalSet);
originalSet = null; // no other references to the originalSet

// Can unmodifiableSet be shared among several threads?  
然后每个线程都会使用如下代码访问它:

synchronized (mySet) {
  // Iterate and read operations
}
根据这种逻辑,一次只能有一个线程在集合上操作。。。
所以我的问题是,对于一个不可修改的集合,当使用诸如for each、
contains
size
等操作时,我真的需要同步访问吗?

根据您的示例,如果它是一个不可修改的
集合,那么您就可以了;因为
String
对象是不可变的。但是,如果它是一组不是不可变的东西,那么必须小心两个线程都试图更改集合中的同一对象

您还必须注意是否有对
集合的引用,这不是不可修改的。一个变量可能是不可修改的,但仍然是指可以通过不同变量修改的
集合
;但您的示例似乎已经涵盖了这一点。

事实上不可变的对象是线程安全的。i、 e.永远不会改变其状态的对象。这包括理论上可以改变但永远不会改变的对象。 但是,其中包含的所有对象也必须是“事实上”不可变的。 此外,当您停止修改对象时,该对象才开始成为线程安全的。 它需要以安全的方式传递给其他线程。有两种方法可以做到这一点

1.)只有在停止修改对象后,才能启动其他线程。在这种情况下,您根本不需要任何同步


2.)在您修改对象时,其他线程已经在运行,但一旦您完成构建对象,您就可以通过同步机制(例如ConcurrentLinkedQue)将其传递给它们。之后,您不需要任何进一步的同步。

任何线程都不能修改不可修改的集合,例如,您不能在集合中添加或删除任何内容,但线程可以修改集合元素的状态,这可能需要同步。@LuigImendoza是write,它取决于包含的元素,如果它们是不可变的,则不需要线程同步,例如,在您提供的示例中,集合包含不可变的
java.lang.String
s,因此您可以删除同步。是这样吗?在不了解装饰对象实现的情况下,如何确保装饰对象是线程安全的?出于性能或其他一些未预料到的原因,包装集不可能在任意时间修改其内部状态吗?我认为简单的HashSet并非如此,但定制实现可能更复杂。
synchronized (mySet) {
  // Iterate and read operations
}