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());