码迷,mamicode.com
首页 > 编程语言 > 详细

Map容器线程安全问题

时间:2018-05-23 02:09:38      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:shm   span   jdk7   安全   tom   tostring   try   apm   情况   

一、HashMap在非线程安全的环境下使用会出现什么样的问题?

public class HashMapMultiThread {  
    static Map<String,String> map = new HashMap<String,String>();  
    public static class AddThread implements Runnable{  
        int start = 0 ;  
        public AddThread(int start){  
            this.start = start;  
        }  
        @Override    
        public void run() {  
            for (int i = 0; i < 100000; i+=2) {  
                map.put(Integer.toString(i), Integer.toBinaryString(i));  
                  
            }  
        }  
    }  
      
    public static void main(String[] args) throws InterruptedException {  
          
        Thread t1 = new Thread(new HashMapMultiThread.AddThread(0));  
        Thread t2 = new Thread(new HashMapMultiThread.AddThread(1));  
        t1.start();  
        t2.start();  
        t1.join();  
        t2.join();  
        System.out.println(map.size());  
    }  
}  

 

上述代码使用t1和t2两个线程同时对HashMap进行put()操作,如果一切正常,我们期望得到的map.size()就是100000.但实际上,你可能会得到以下三种情况(注意,这里使用JDK7进行试验): 

第一:程序正常结束,并且结果也是符合预期的。HashMap的大小为100000.

第二:程序正常结束,但结果不符合预期,而是一个小于100000的数字,比如98868.

第三:程序永远无法结束。并发形成循环链表,导致死循环。

二、ConcurrentHashMap不能解决所有线程安全问题

对于ConcurrentHashMap,如果只调用get或put方法是线程安全的,但你调用get后再调用put之前,如果有另一个线程也调用了put就很可能把前面的操作结果覆盖了,因为违反了原则操作的规则。此时可用putIfAbsent方法代替。如下面的例子

public class ConcurrentHashMapTest {

    private static final ConcurrentMap<String, AtomicInteger> CACHE_MAP = new ConcurrentHashMap<>();
    private static final String KEY = "test";

    private static class TestThread implements Runnable{
        @Override
        public void run() {
            if(CACHE_MAP.get(KEY)==null){
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                CACHE_MAP.put(KEY, new AtomicInteger());
            }
            CACHE_MAP.get(KEY).incrementAndGet();
        }
    }

    public static void main(String[] args) {
        new Thread(new TestThread()).start();
        new Thread(new TestThread()).start();
        new Thread(new TestThread()).start();
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("次数:"+CACHE_MAP.get(KEY).get());
    }
}

 

Map容器线程安全问题

标签:shm   span   jdk7   安全   tom   tostring   try   apm   情况   

原文地址:https://www.cnblogs.com/doit8791/p/9074829.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!