首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java.util.concurrent藏品的安全发布

java.util.concurrent藏品的安全发布
EN

Stack Overflow用户
提问于 2012-08-29 11:39:47
回答 6查看 720关注 0票数 6

在此代码中易失性是多余的吗?

代码语言:javascript
复制
public class Test {
    private volatile Map<String, String> map = null;

    public void resetMap() { map = new ConcurrentHashMap<>(); }

    public Map<String, String> getMap() { return map; }
}

换句话说,map = new ConcurrentHashMap<>();是否提供了任何可见性保证?

据我所见,ConcurrentMap提供的唯一保证是:

在将对象作为键或值放置到ConcurrentMap之前,线程中的操作发生在访问或删除另一个线程中的ConcurrentMap之后的操作之前。

java.util.concurrent (CopyOnWriteArrayList等)中的其他线程安全集合如何?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-08-29 11:46:07

volatile并不是多余的,因为您正在更改对映射的引用。也就是说,ConcurrentMap只提供有关集合内容的监护人,而不提供对它的引用。

另一种选择是

代码语言:javascript
复制
public class Test {
    private final Map<String, String> map = new ConcurrentHashMap<>();

    public void resetMap() { map.clear(); }

    public Map<String, String> getMap() { return map; }
}

java.util.concurrent (CopyOnWriteArrayList等)中的其他线程安全集合如何?

只有集合的行为才是线程安全的。对集合的引用不是线程安全的,集合中的元素通过将它们添加到集合中而不是线程安全。

票数 8
EN

Stack Overflow用户

发布于 2012-08-29 11:47:53

volatile在这里是必要的。它适用于引用,而不适用于它所引用的内容。换句话说,一个对象是否是线程安全并不重要,其他线程不会看到map字段的新值(例如,可能会看到以前引用的并发映射或null)。

此外,即使您的对象是不可变的(例如String),您仍然需要volatile,更不用说其他线程安全的集合了,比如CopyOnWriteArrayList

票数 6
EN

Stack Overflow用户

发布于 2012-08-29 11:52:45

这不仅仅是参考资料的问题。通常,如果没有volatile修饰符,其他线程可能会观察到对对象的新引用,但会观察到对象处于部分构造的状态。一般来说,即使在查阅了文档之后,也不容易知道哪些对象是安全的,可以通过数据竞赛发布。一个有趣的注意是,JLS确实为线程安全的不可变对象保证了这一点,所以如果文档提到这两个属性,那就足够了。

ConcurrentHashMap显然不是一个不可变的对象,所以这不适用,而且文档没有提到任何有关数据竞争发布的内容。通过对源代码的仔细检查,我们可以得出结论,它确实是安全的,但是,如果没有明确的文档记录,我不建议依赖这样的发现。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12177081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档