Java 最终的hashmap是线程安全的

Java 最终的hashmap是线程安全的,java,multithreading,synchronization,thread-safety,final,Java,Multithreading,Synchronization,Thread Safety,Final,map变量似乎不是线程安全的,这是为什么?然而下面的方法似乎有效,这是为什么 volatile HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); 使用Collections.unmodifiableMap(map)是否有效?线程安全的是访问map变量:所有读取该变量的线程都将看到相同的对象引用 但是,HashMap(get/put)上的操作不是线程安全的,这与map是否为final无关 因此,除

map
变量似乎不是线程安全的,这是为什么?然而下面的方法似乎有效,这是为什么

volatile HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();

使用
Collections.unmodifiableMap(map)
是否有效?

线程安全的是访问
map
变量:所有读取该变量的线程都将看到相同的对象引用

但是,HashMap(get/put)上的操作不是线程安全的,这与
map
是否为final无关


因此,除非围绕
putValue
方法添加一些并发控制,否则您的代码不是线程安全的-例如,通过使其
同步

使引用变量为final,确保引用变量不能更改已分配给它的对象引用

但物体的价值可能会改变。同样的事情发生在这里,你的对象值可能会改变。现在需要同步更改值的代码。 使用
ConcurrentHashMap
可以消除所有同步问题。你可以读到它


使用
ConcurrentHashMap
确保对象上的每个写入操作一次只能由一个线程处理。它还优化了HashMap的读取。它将
HashMap
划分为块,不同的线程可能从不同的块读取数据。

您的测试失败。如果使用相同的
键存储两个
。因此,即使没有并发,您的“测试”也将返回大小为
1

代码:

有时可以看到大小为
0
的事实是由于缺少块构造。在通过调用查询yur映射的大小之前,应该等待两个
线程的完成

final
不会使您的代码线程安全,
volatile
在这种情况下不会切断它

如果需要线程安全哈希映射,请使用


如果您决定编写自己的线程安全实现,我建议您从开始,然后可能是一点点。

您的问题的直接答案是:否,final关键字不会使字段线程安全

该关键字只告诉编译器,它必须确保为该字段指定了一个值(而不是零个或多个赋值)

您知道,获取多线程代码正确被认为是困难的原因有很多

正确的多线程的本质是:当一些状态可以由一个线程更新,但被其他线程使用(或更新)时。。以确保您只获得希望看到的状态更改


长话短说:你有很多东西要学;一个很好的起点是。

我认为您的代码可能是重复的,因为您创建的两个线程可以同时交错和修改映射。我已经浏览了链接,但我不清楚这就是为什么我发布了这个问题。我应该得到答案为2为什么1或0提交并声明为最终结果.Final是线程安全的。为什么您认为应该获得2?HashMap不是线程安全的-这意味着映射上并发操作的结果是未定义的。0、1、2或-13都是合法输出。@coder25您的假设是错误的。正如前面所解释的那样,对象本身是线程安全的,但不是它的字段。因此hashmap对象(引用)是线程安全的,但对其执行的任何操作都不是线程安全的,除非使用
synchronized
final
不是将对象转换为线程安全对象的神奇关键字。如果我使用易失性变量,那么它也不起作用。使用它works@coder25volatile与final一样,修改应用它的变量的语义,而不是底层对象。
volatile HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
public  synchronized void putValue(int key,int value){
    if(map.isEmpty()){
        System.out.println("hello");
        map.put(key,value);     
}
import java.util.HashMap;

public class MapDem {

    final HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();

    public HashMap<Integer, Integer> getMap() {
        return map;
    }

    public void putValue(int key, int value) {
        map.put(key, value);
    }

    public static void main(String args[]) {
        MapDem demo = new MapDem();

        demo.putValue(1, 10);
        demo.putValue(1, 10);

        System.out.println(demo.getMap().size());
    }
}
1
            Thread t1 = new Thread(new Runnable() {

                @Override
                public void run() {
                    demo.putValue(1, 10);

                }

            });
            t1.start();

            Thread t2 = new Thread(new Runnable() {

                @Override
                public void run() {
                    demo.putValue(1, 10);

                }

            });
            t2.start();

            try {
                t1.join();
                t2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(demo.getMap().size());