同步Set线程的构造函数是否安全?

时间:2013-07-12 14:04:34

标签: java

获取 java.util.Set 的同步版本的最简单方法是使用 Collections.synchronizedSet(),如下所示:

Set mySyncSet = Collections.synchronizedSet(new HashSet());

Java API说明了这个新对象:

  

当迭代它时,用户必须手动同步返回的集合

我的问题是,如果我使用这样的复制构造函数创建此 Set 的副本:

Set mySetCopy = new HashMap(mySyncSet);

它是线程安全的吗? (不是HashMap构造函数使用迭代来获取 Set 的成员吗?)或者我应该手动同步这样的操作吗?:

Set mySetCopy;

synchronized(mySyncSet) {
    mySetCopy = new HashMap(mySyncSet);
}

2 个答案:

答案 0 :(得分:9)

让我们来看看代码:

public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}

只需拨打addAll

即可
public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

所以这会循环你提供的Collection

答案是否定的,构造函数副本线程安全。

您需要使用第二个选项,并在synchronized上显式Set,然后再将其传递给构造函数。

答案 1 :(得分:0)

第二种方式更可取。如果某个线程修改了你的原始线程,当这个线程迭代你的集合以复制对你的新集合的引用时,你将遇到麻烦。

访问或修改集合的所有代码都应在 同一实例 上手动同步,如JavaDoc指定的那样。

相关问题