一:hashMap线程不安全表现
(1)在两个线程同时尝试扩容HashMap时,可能将一个链表形成环形的链表,所有的next都不为空,进入死循环;
(2)在两个线程同时进行put时可能造成一个线程数据的丢失;
二:如何线程安全的使用hashMap
(1)Hashtable
//Hashtable
Map<String, String> hashtable =
new
Hashtable<>();
HashTable源码中是使用synchronized
来保证线程安全的,比如下面的get方法和put方法:
1 2 3 4 5 6 |
|
所以当一个线程访问HashTable的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。举个例子,当一个线程使用put方法时,另一个线程不但不可以使用put方法,连get方法都不可以,所以效率很低,基本不会选择它。
(2)ConcurrentHashMap
//ConcurrentHashMap
Map<String, String> concurrentHashMap =
new
ConcurrentHashMap<>();
在jdk1.8中ConcurrentHashMap利用CAS算法
(3)SynchronizedMap
//synchronizedMap
Map<String, String> synchronizedHashMap = Collections.synchronizedMap(
new
HashMap<String, String>());
|
从源码中可以看出调用synchronizedMap()方法后会返回一个SynchronizedMap类的对象,而在SynchronizedMap类中使用了synchronized同步关键字来保证对Map的操作是线程安全的。