Java并发:是final字段(在构造函数中初始化)线程安全? [英] Java concurrency: is final field (initialized in constructor) thread-safe?

查看:1103
本文介绍了Java并发:是final字段(在构造函数中初始化)线程安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以告诉我这个类是否是线程安全的吗?

Can anyone tell me whether this class is threadsafe or not ?

class Foo {

    private final Map<String,String> aMap;

    public Foo() {
        aMap = new HashMap<String, String>();
        aMap.put("1", "a");
        aMap.put("2", "b");
        aMap.put("3", "c");
    }

    public String get(String key) {
        return aMap.get(key);
    }

}

编辑:澄清问题。根据 JMM常见问题

It my fault to not clarify the question. According to JMM FAQ :


应提供初始化安全性的新保证。如果对象被正确构造(这意味着对它的引用在构造期间不会转义),那么看到对该对象的引用的所有线程也将看到在构造函数中设置的其最终字段的值,而不需要同步。

A new guarantee of initialization safety should be provided. If an object is properly constructed (which means that references to it do not escape during construction), then all threads which see a reference to that object will also see the values for its final fields that were set in the constructor, without the need for synchronization.

这让我困惑的是aMap的集合 aMap = new HashMap< String,String> ; 。所以其他线程可以看到这些

This made me confuse that the set to aMap is aMap = new HashMap<String, String>();. So other threads can see these

aMap.put("1", "a");
aMap.put("2", "b");
aMap.put("3", "c");

吗?

发现此问题完全关闭了我的问题

I found this question that exactly closed to my question

推荐答案

正如已经指出的,它绝对是线程安全的, final

As already pointed out it's absolutely thread-safe, and final is important here due to its memory visibility effects.

存在 final 可以保证其他线程将看到值构造函数完成后的映射没有任何外部同步。如果没有 final ,则无法保证在所有情况下,并且在使新建构对象可用于其他线程时,您需要使用安全发布成语,即(来自 Java并发实践):

Presence of final guarantees that other threads would see values in the map after constructor finished without any external synchronization. Without final it cannot be guaranteed in all cases, and you would need to use safe publication idioms when making newly constructed object available to other threads, namely (from Java Concurrency in Practice):



  • 从静态初始化程序初始化对象引用;

  • 将对其的引用存储到volatile字段或AtomicReference中;

  • 将其引用到正确构造的对象的最终字段中;

这篇关于Java并发:是final字段(在构造函数中初始化)线程安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆