java - 同步 Set 线程的构造函数副本是否安全?

标签 java

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

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

Java API说到这个新对象:

It is imperative that the user manually synchronize on the returned set when iterating over it

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

Set mySetCopy = new HashMap(mySyncSet);

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

Set mySetCopy;

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

最佳答案

让我们看一下代码:

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

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

在将 Set 传递给构造函数之前,您需要使用第二个选项并在 Set 上执行显式 synchronized

关于java - 同步 Set 线程的构造函数副本是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17616784/

相关文章:

带有 ArrayList 的 Java for 循环

java - 关于 Mockito 的一些帮助

java - 我的 jsp 中的标签库错误

java - 无法使用 Maven 运行 JUnit5 测试

java - ConstructorProperties注释不起作用

java - 在 libGdx 中加载 Vector2 数组时出现问题

java - 删除ArrayList中每个索引的前导空格

AWS lambda 中的 Java 8 并发?

java - 在 Android Studio 中,如何将应用程序项目更改为库?

java - JFrame我应该怎么做(包括图片)?