<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

    關注后端架構、中間件、分布式和并發編程

       :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks

    大家都知道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原理的文章。 __ by xylz 2010.07.20


    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2009-12-18 18:20 imxylz 閱讀(6164) 評論(2)  編輯  收藏 所屬分類: J2EE技術

    評論

    # re: HashMap的讀寫并發 2009-12-31 11:27 bing
    很有意思,謝謝!  回復  更多評論
      

    # re: HashMap的讀寫并發[未登錄] 2010-07-20 15:38 test
    是hashcode的index變了,而不是hashcode變了,0L的hashcode應該會始終不變的。  回復  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 国产精成人品日日拍夜夜免费| 国产精品亚洲片在线花蝴蝶| 免费国产成人α片| 亚洲人成网站999久久久综合| 中国人xxxxx69免费视频| 亚洲一区二区三区首页| 国产在线观看麻豆91精品免费 | 在线不卡免费视频| 国产成人精品日本亚洲语音 | 国产又大又长又粗又硬的免费视频| 亚洲大尺度无码无码专线一区| 国产极品粉嫩泬免费观看| 精品成人一区二区三区免费视频| 亚洲五月午夜免费在线视频| 在线观看免费黄色网址| 亚洲色图校园春色| 国产小视频在线观看免费| A级毛片成人网站免费看| 亚洲国产综合专区在线电影| av免费不卡国产观看| 亚洲av无码成人精品国产| 亚洲综合久久夜AV | 久久香蕉国产线看免费| 亚洲最大无码中文字幕| 暖暖免费日本在线中文| 国产精品高清视亚洲精品| 国产精品视频免费一区二区三区 | 国产成人精品日本亚洲专区 | 亚洲电影国产一区| 成年性午夜免费视频网站不卡| 黄色三级三级免费看| 亚洲va久久久噜噜噜久久天堂| 歪歪漫画在线观看官网免费阅读| 免费一级特黄特色大片 | 亚洲精品美女久久久久久久| 亚洲人成无码网WWW| 亚洲视频在线免费看| 免费国产va在线观看| 亚洲成a人片77777群色| 亚洲伊人久久综合影院| 在线观看成人免费视频不卡|