Java中的最终静态变量是否是线程安全的? [英] Are final static variables thread safe in Java?

查看:141
本文介绍了Java中的最终静态变量是否是线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个看起来像这样的类:

$ b我已经读了很多,但还没有找到明确的答案。
$ b

  public class Foo(){

private static final HashMap< String,HashMap> sharedData;

private final HashMap myRefOfInnerHashMap;

static {
//耗时初始化sharedData
final HashMap< String,String> innerMap = new HashMap< String,String> ;;
innerMap.put ...
innerMap.put ...
... a

sharedData.put(someKey,java.util.Collections.unmodifiableMap( innerMap));
}

public Foo(String key){
this.myRefOfInnerHashMap = sharedData.get(key); (Map.Entry< String,String>条目:this.myRefOfInnerHashMap.entrySet()返回复制
的复制代码


public void doSomethingUseful )){
...
}
}
}

我想知道从Foo的实例访问共享数据是否是线程安全的(如构造函数和doSomethingUseful()中所示)。 Foo的许多实例将在多线程环境中创建。



我的意图是sharedData在静态初始化器中被初始化,并且之后没有被修改(只读)。

我读过的是不可变对象本质上是线程安全的。但是我只是在似乎是实例变量的上下文中看到了这一点。是不可变的静态变量线程安全吗?



我发现的另一个构造是一个ConcurrentHashMap。我可以创建类型为ConcurrentHashMap的sharedData,但是它包含的HashMaps也必须是ConcurrentHashMap类型?基本上..

  private static final ConcurrentHashMap< String,HashMap> sharedData; 

  private static final ConcurrentHashMap< String,ConcurrentHashMap> sharedData; 

或者它会更安全(简单地clone()更昂贵)?

  this.myCopyOfData = sharedData.get(key).clone(); 

TIA。

参考改为共享数据最终是线程安全的,因为它永远不会被改变。 Map的内容是非线程安全的,因为它需要用Guava ImmutableMap 实现或 java来包装.util.Collections.unmodifiableMap()或使用 java.util.concurrent 包中的一个Map实现。



只有在 BOTH 的情况下,您才能在地图上拥有全面的线程安全性。任何包含的地图都必须是不可变的,或者是一个并发实现。



.clone()基本上被打破,远离$ / b
$ b

默认情况下为克隆,它只是返回对容器对象的引用而不是完整的副本。有关为什么一般可用的信息很好地记录。


I've read around quite a bit but haven't found a definitive answer.

I have a class that looks like this:

    public class Foo() {

        private static final HashMap<String, HashMap> sharedData;

        private final HashMap myRefOfInnerHashMap;

        static {
           // time-consuming initialization of sharedData
           final HashMap<String, String> innerMap = new HashMap<String, String>;
           innerMap.put...
           innerMap.put...
           ...a

           sharedData.put(someKey, java.util.Collections.unmodifiableMap(innerMap));
        }

        public Foo(String key) {
            this.myRefOfInnerHashMap = sharedData.get(key);
        }

        public void doSomethingUseful() {
            // iterate over copy
            for (Map.Entry<String, String> entry : this.myRefOfInnerHashMap.entrySet()) {
                ...
            }
        }
     }

And I'm wondering if it is thread safe to access sharedData from instances of Foo (as is shown in the constructor and in doSomethingUseful()). Many instances of Foo will be created in a multi-threaded environment.

My intention is that sharedData is initialized in the static initializer and not modified thereafter (read-only).

What I've read is that immutable objects are inherently thread safe. But I've only seen this in what seems to be the context of instance variables. Are immutable static variables thread safe?

The other construct I found was a ConcurrentHashMap. I could make sharedData of type ConcurrentHashMap but do the HashMaps it contains also have to be of type ConcurrentHashMap? Basically..

private static final ConcurrentHashMap<String, HashMap> sharedData;

or

private static final ConcurrentHashMap<String, ConcurrentHashMap> sharedData;

Or would it be safer (yet more costly to simply clone())?

this.myCopyOfData = sharedData.get(key).clone();

TIA.

(Static initializer has been edited to give more context.)

解决方案

the reference to sharedData which is final is thread safe since it can never be changed. The contents of the Map is NOT thread safe because it needs to be either wrapped with preferably a Guava ImmutableMap implementation or java.util.Collections.unmodifiableMap() or use one of the Map implementations in the java.util.concurrent package.

Only if you do BOTH will you have comprehensive thread safety on the Map. Any contained Maps need to be immutable or one of the concurrent implementations as well.

.clone() is fundamentally broken, stay away

cloning by default is a shallow clone, it will just return references to container objects not complete copies. It is well documented in generally available information on why.

这篇关于Java中的最终静态变量是否是线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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