`
ikon
  • 浏览: 107850 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hashmap线程不安全在哪里?

 
阅读更多

大家都知道HashMap不是线程安全的,但是大家的理解可能都不是十分准确。很显然读写同一个key会导致不一致大家都能理解,但是如果读写一个不变的对象会有问题么?看看下面的代码就明白了。

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 import java.util.Random;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.Executors;
 6 import java.util.concurrent.TimeUnit;
 7 import java.util.concurrent.atomic.AtomicInteger;
 8 
 9 public class HashMapTest2 {
10     static void doit() throws Exception{
11         final int count = 200;
12         final AtomicInteger checkNum = new AtomicInteger(0);
13         ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(100);
14         //
15         final Map<Long, String> map = new HashMap<Long, String>();
16         map.put(0L"www.imxylz.cn");
17         //map.put(1L, "www.imxylz.cn");
18         for (int j = 0; j < count; j++) {
19             newFixedThreadPool.submit(new Runnable() {
20                 public void run() {
21                     map.put(System.nanoTime()+new Random().nextLong(), "www.imxylz.cn");
22                     String obj = map.get(0L);
23                     if (obj == null) {
24                         checkNum.incrementAndGet();
25                     }
26                 }
27             });
28         }
29         newFixedThreadPool.awaitTermination(1, TimeUnit.SECONDS);
30         newFixedThreadPool.shutdown();
31         
32         System.out.println(checkNum.get());
33     }
34     
35     public static void main(String[] args) throws Exception{
36         for(int i=0;i<10;i++) {
37             doit();
38             Thread.sleep(500L);
39         }
40     }
41 }
42 

结果一定会输出0么?结果却不一定。比如某一次的结果是:

 

0
3
0
0
0
0
9
0
9
0

 

查看了源码,其实出现这个问题是因为HashMap在扩容是导致了重新进行hash计算。

在HashMap中,有下面的源码:

 

 1     public V get(Object key) {
 2         if (key == null)
 3             return getForNullKey();
 4         int hash = hash(key.hashCode());
 5         for (Entry<K,V> e = table[indexFor(hash, table.length)];
 6              e != null;
 7              e = e.next) {
 8             Object k;
 9             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
10                 return e.value;
11         }
12         return null;
13     }

 

在indexOf中就会导致计算有偏移。

1 static int indexFor(int h, int length) {
2         return h & (length-1);
3     }

 

很显然在Map的容量(table.length,数组的大小)有变化时就会导致此处计算偏移变化。这样每次读的时候就不一定能获取到目标索引了。为了证明此猜想,我们改造下,变成以下的代码。

final Map<String, String> map = new HashMap<String, String>(10000);

执行多次结果总是输出:

 

0
0
0
0
0
0
0
0
0
0

 

当然了如果只是读,没有写肯定没有并发的问题了。改换Hashtable或者ConcurrentHashMap肯定也是没有问题了。

 

分享到:
评论

相关推荐

    关于如何解决HashMap线程安全问题的介绍

    但是需要注意,虽然这个方法可以保证基本的线程安全,但迭代仍然是非线程安全的,即不能在遍历过程中修改Map。 2. 使用ConcurrentHashMap:Java从1.5版本开始引入了ConcurrentHashMap,它是线程安全且高并发性能的...

    【并发】为什么HashMap是线程不安全的?

    经常会看到说HashMap是线程不安全的,ConcurrentHashMap是线程安全的等等说法,不禁有个疑问,什么是线程安全?什么样的类是线程安全的? 1.什么是线程安全性(what) 线程安全定义,最核心是正确性, 正确性:多个...

    高级程序员必会的HashMap的线程安全问题,适用于0~2年的.7z

    然而,对于多线程环境,HashMap并不是线程安全的,这在并发编程中可能会引发一系列问题。本篇将深入探讨HashMap的线程安全问题,并提供相关的解决方案。 首先,我们需要了解HashMap在多线程环境下可能出现的问题: ...

    通过代码证明HashMap是线程不安全的(只用了一个Java文件)

    `HashMap`在设计时并未考虑线程安全,因此在并发场景下,如果不采取适当的同步措施,可能会遇到诸如数据丢失、死锁等问题。 `HashMap`的核心实现是基于哈希表的,它使用了数组和链表的数据结构。当多个线程同时对`...

    HashMap和HashTable的区别?但是如果想线程安全有想效率高?

    HashMap和HashTable的区别?但是如果想线程安全有想效率高?

    servlet线程安全问题

    Servlet 线程安全问题是指在使用 Servlet 编程时,如果不注意多线程安全性问题,可能会导致难以发现的错误。Servlet/JSP 技术由于其多线程运行而具有很高的执行效率,但这也意味着需要非常细致地考虑多线程的安全性...

    hashmap-thread-test:测试 Java HashMap 是否是线程安全的

    然而,`HashMap`并非线程安全,这意味着在多线程环境中直接使用`HashMap`可能会导致数据不一致、并发问题,甚至程序崩溃。本项目“hashmap-thread-test”显然是为了测试和展示这一特性。 ### Java HashMap 的特性 ...

    第9讲 对比Hashtable、HashMap、TreeMap有什么不同?1

    在并发环境下,HashMap的非线程安全可能导致死循环(例如,多个线程同时进行扩容操作)和其他并发问题。 了解Map的整体结构也很重要,HashMap和其他Map实现如LinkedHashMap(保持插入顺序或访问顺序的HashMap)都是...

    HashMap夺命连环问面试题分享给需要同学.docx

    模拟面试之HashMap ...\ ...7.HashMap是线程安全的吗? 追问:如何解决这个线程不安全的问题? 追问:分别讲一下这几种Map都是如何实现线程安全的? 8.说一下HashMap在JDK1.8中都有哪些改变? 9.HashM

    都说 HashMap 是线程不安全的,到底体现在哪儿?.zip

    计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料计算机技术、IT咨询、人工智能AI理论介绍,学习...

    hashmap面试题_hashmap_

    答:在多线程环境下,可以使用ConcurrentHashMap,它是线程安全的HashMap实现。 五、HashMap与HashSet的关系 HashSet基于HashMap实现,每个元素作为HashMap的一个键,值为null。因此,HashSet的操作性能也依赖于...

    java的hashMap多线程并发情况下扩容产生的死锁问题解决.docx

    此外,引入了ConcurrentHashMap类,这是一个专门为多线程设计的高效容器,其内部使用分段锁策略,可以在并发环境下保证线程安全,避免了类似HashMap扩容引发的死锁问题。 如果你在多线程环境中使用HashMap并遇到...

    一文精通HashMap灵魂七问,你学还是不学.doc

    3. **为什么不在一开始就使用红黑树?** 这是考虑到空间和性能之间的平衡。红黑树节点占用的空间是链表节点的两倍,所以只有当链表足够长时,转换才划算。转换的阈值(默认8)是根据哈希冲突的概率和一般应用需求来...

    ArrayList集合与HashMap的扩容原来.docx

    HashMap 是线程不安全的,可以通过以下三种方式解决线程安全问题: 1. Hashtable(以过时),是在底层哈希表添加了一把锁 synchronized; 2. ConcurrentHashMap,jdk1.7 添加了分段锁,就是在底层数组上,几个索引...

    File、HashMap线程不安全、IO流、封装的感想、数据类型 转换、异常

    以结构图记录自己的记录自己面对的感触

    HashMap源码分析系列-第四弹:HashMap多线程解决方案.docx

    #### 二、HashMap线程安全问题分析 在多线程环境中,`HashMap`的主要线程安全问题包括但不限于: 1. **链表死循环问题**:在JDK 1.7中,当多个线程同时进行`put`操作时,可能会出现链表死循环的情况,这是一个严重...

    Go-Golang无锁线程安全的HashMap为最快的读取访问进行了优化

    本文将深入探讨如何利用Go语言构建一个无锁线程安全的HashMap,特别关注其优化读取访问速度的设计策略。 HashMap是编程中常见的数据结构,用于存储键值对。在多线程环境中,为了保证数据的一致性和正确性,通常需要...

    HashMap和HashTable底层原理以及常见面试题

    1. 线程安全:HashMap不是线程安全的,而HashTable是线程安全的。 2. 性能:HashMap的性能比HashTable好,因为HashMap使用数组和链表来存储键值对,而HashTable使用链表来存储键值对。 3. null键:HashMap允许存放...

    Java多线程安全集合

    线程安全是指一个类或者方法在多线程环境中被调用时,能够正确地处理并发访问,不会因为线程间的交互而产生错误或不确定的行为。在Java中,线程安全的集合主要分为三类:同步集合、并发集合和不可变集合。 1. 同步...

    Java集合多线程安全.docx

    然而,并非所有集合类都是线程安全的,这在多线程环境中可能导致数据不一致或者运行时异常。线程安全指的是一个对象在多线程环境下可以被正确地访问和修改,而不会出现竞态条件或死锁等问题。 线程不安全的集合类...

Global site tag (gtag.js) - Google Analytics