简体   繁体   English

最终不可修改的套件是否安全?

[英]Are final unmodifiable sets thread safe?

The javadocs are not clear about this: are unmodifiable sets thread safe? javadocs对此不清楚:不可修改的设置线程安全吗? Or should I worry about internal state concurrency problems? 或者我应该担心内部状态并发问题?

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?  

I have stumbled upon a piece of code with a static, read-only Set being shared against multiple threads... The original author wrote something like this: 我偶然发现了一段代码,其中包含一个静态的只读Set它与多个线程共享......原作者写了这样的东西:

mySet = Collections.synchronizedSet(Collections.unmodifiableSet(originalSet));

And then every thread access it with code such as: 然后每个线程使用以下代码访问它:

synchronized (mySet) {
  // Iterate and read operations
}

By this logic only one thread can operate on the Set at once... So my question is, for a unmodifiable set, when using operations such as for each , contains , size , etc, do I really need to synchronize access? 通过这个逻辑,只有一个线程可以立即对Set进行操作...所以我的问题是,对于一个不可修改的集合,当使用诸如每个containssize等操作时,我真的需要同步访问吗?

If it's an unmodifiable Set<String> , as per your example, then you're fine; 如果它是一个不可修改的Set<String> ,根据你的例子,那你很好; because String objects are immutable. 因为String对象是不可变的。 But if it's a set of something that's not immutable, you have to be careful about two threads both trying to change the same object inside the set. 但是如果它是一组不可变的东西,你必须要小心两个线程都试图改变集合中的同一个对象。

You also have to be careful about whether there's a reference somewhere to the Set , that's not unmodifiable. 你还必须要小心是否在Set某个地方有一个引用,这不是不可修改的。 It's possible for a variable to be unmodifiable, but still be referring to a Set which can be modified via a different variable; 变量可能是不可修改的,但仍然指的是可以通过不同变量修改的Set ; but your example seems to have that covered. 但你的例子似乎已经覆盖了。

Objects that are "de facto" immutable are thread safe. “事实上”不可变的对象是线程安全的。 ie objects that never change their state. 即永远不会改变其状态的对象。 That includes objects that could theoretically change but never do. 这包括理论上可以改变但永远不会改变的对象。 However all the objects contained inside must also be "de facto" immutable. 但是,里面包含的所有对象也必须是“事实上”不可变的。 Furthermore the object only starts to become thread safe when you stop modifying it. 此外,当您停止修改对象时,该对象才开始变为线程安全。 And it needs to be passed to the other threads in a safe manner. 它需要以安全的方式传递给其他线程。 There are 2 ways to do that. 有两种方法可以做到这一点。

1.) you start the other threads only after you stopped modifying your object. 1.)只有在停止修改对象后才启动其他线程。 In that case you don't need any synchronization at all. 在这种情况下,您根本不需要任何同步。

2.) the other threads are already running while you are modifying the object, but once you completed constructing the object, you pass it to them through a synchronized mechanism eg a ConcurrentLinkedDeque. 2.)在修改对象时,其他线程已在运行,但是一旦完成对象的构建,就会通过同步机制(例如ConcurrentLinkedDeque)将其传递给它们。 After that you don't need any further synchronization. 之后,您不需要任何进一步的同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM