2.hashMap如何保证线程安全

一: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

public synchronized V get(Object key) {

       // 省略实现

    }

public synchronized V put(K key, V value) {

    // 省略实现

    }

        所以当一个线程访问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方法

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {

       return new SynchronizedMap<>(m);

   }

// SynchronizedMap类

private static class SynchronizedMap<K,V>

       implements Map<K,V>, Serializable {

       private static final long serialVersionUID = 1978198479659022715L;

 

       private final Map<K,V> m;     // Backing Map

       final Object      mutex;        // Object on which to synchronize

 

       SynchronizedMap(Map<K,V> m) {

           this.m = Objects.requireNonNull(m);

           mutex = this;

       }

 

       SynchronizedMap(Map<K,V> m, Object mutex) {

           this.m = m;

           this.mutex = mutex;

       }

 

       public int size() {

           synchronized (mutex) {return m.size();}

       }

       public boolean isEmpty() {

           synchronized (mutex) {return m.isEmpty();}

       }

       public boolean containsKey(Object key) {

           synchronized (mutex) {return m.containsKey(key);}

       }

       public boolean containsValue(Object value) {

           synchronized (mutex) {return m.containsValue(value);}

       }

       public V get(Object key) {

           synchronized (mutex) {return m.get(key);}

       }

 

       public V put(K key, V value) {

           synchronized (mutex) {return m.put(key, value);}

       }

       public V remove(Object key) {

           synchronized (mutex) {return m.remove(key);}

       }

       // 省略其他方法

   }

      从源码中可以看出调用synchronizedMap()方法后会返回一个SynchronizedMap类的对象,而在SynchronizedMap类中使用了synchronized同步关键字来保证对Map的操作是线程安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值