成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

阿里二面:聽說過 HashMap 會導致CPU飆升100%嗎?

開發
雖然 Java 官方明確表示,在多線程環境下不推薦使用 HashMap,但是對于這種問題,小編其實也比較意外,如果不是深入的去了解 HashMap,都不知道有這樣的問題。

一、問題描述

經常有些面試官會問,是否了解過 HashMap 在多線程環境下使用時可能會發生死循環,導致服務器 cpu 100% 的線上故障?

關于這個問題,很多年前,在淘寶內網里就有很多的程序員發過這種帖子說一個CPU 被100%了,原因竟是多線程環境下使用 HashMap 造成的死循環,并且這個事發生了很多次。

雖然 Java 官方明確表示,在多線程環境下不推薦使用 HashMap,但是對于這種問題,小編其實也比較意外,如果不是深入的去了解 HashMap,都不知道有這樣的問題。

為什么會產生死循環呢?下面我們來還原一下問題的經過。

二、問題重現

在之前的集合系列文章中,我們了解到 HashMap 是一個哈希數組 + 鏈表的數據結構,在實際的程序開發中,我們經常會使用到 HashMap,如果對 HashMap 不是很了解,大家可以看小編之前寫的《深入淺出分析 HashMap 》一文。

HashMap 是一個非線程安全的集合操作類,如果我們的程序操作是單線程的,那么一切都沒問題。當我們的程序是多線程操作 HashMap 類時,那么問題就來了,我們一起來復現一下。

測試代碼,如下:

使用了4個線程來向 HashMap 中添加元素,可能一次運行不一定有效果,可以反復運行幾次!

控制臺輸出結果:

可以清晰的看到,在遍歷 map 的內容時,已經死循環了!

再來看看,活動監視器,結果如下:

cpu 的使用率,直接接近 200%!

接下來我們去查看下 java 中剛剛運行的 HashThreadTest 類堆棧情況:

可以看到,HashMap 的擴容操作導致了死循環!

通過測試,我們發現 HashMap 在多線程環境下進行操作,的確會產生死循環,并且會導致 CPU 100%!

這是為什么呢?我們一起來閱讀一下源碼!

三、源碼閱讀

注意注意,小編在進行測試的時候,使用的是 JDK1.7 的版本!

如果你使用 JDK1.8 的版本,不好意思,不一定能復現這個問題!因為 JDK1.8 已經修復了這個問題,但是依然不建議在多線程環境下使用 HashMap!

我們繼續來看看為什么使用 JDK1.7 會出現這個問題!

既然是 put 階段造成的數據問題,我們不妨一起來看看 HashMap 的 put 過程!

1.HashMap 添加過程

HashMap 的 put 源碼實現如下:

接著我們來看看addEntry()方法,將元素插入到數組中,并且檢查容量是否超標,源碼實現如下:

上面例子中,我們初始化的時候給定的容量是 2,所以在添加元素時必定會擴容!如果超出閥值,就進行擴容處理,創建一個更大容量的 hash 表,然后把從老的 Hash 表中遷移到新的 Hash 表中,源碼如下:

將舊 hash 表中的元素復制到新的 hash 表中,源碼如下:

整個 put 過程,大致可以分如下幾個步驟:

  • 第一步是通過 key 計算出來的 hash 和 equals 來判斷元素是否存在,如果存在,直接覆蓋;反之,插入;
  • 第二步是將元素插入到 hash 表中,如果不同的元素都在一個 hash 數組下標下,就以鏈表的形式,采用頭插法存儲在 hash 節點下;
  • 最后就是判斷當前數組容量是否大于擴容閥值,如果大于,就進行擴容處理,然后將舊元素復制到新的數組中;

好了,這個過程基本上沒啥問題。

我們再來演示一下擴容中重新計算元素 hash 的過程!

2.單線程下擴容元素 hash 過程

假設在單線程環境下,我們初始化的時候,給定的數組容量是2,分別添加3個元素,內容如下:

  • key=3,value=A;
  • key=4,value=B;
  • key=5,value=C;

源碼如下:

添加完成之后,數組就會進行擴容處理,擴容后 hash 的容量為原來的2倍,擴容操作流程如下:

在單線程環境下,一切看起來都很正常,擴容過程也相當順利。接下來我們看下并發情況下的擴容。

3.多線程擴容元素 hash 過程

假設我們有兩個線程,來分別添加3個元素。

線程二執行完添加任務之后,在準備將舊元素遷移到新元素的時候,也就是準備 rehash 時,突然被 CPU 掛起,此時阻塞在如下圖中的第57行,不再往下執行!而線程一繼續執行直到擴容完成。

2個線程此時的執行結果,內容如下:

接著線程二被喚醒,繼續回到第57行執行。

此時注意了,我們來詳細的分析一下這個過程!

第一次循環過程如下:

  • 第1步:此時 e 等于{key:3,value:A},next=e.next={key:5,value:C};
  • 第2步:通過 key 重新 hash 計算得到下標 i = 3;
  • 第3步:newTable為局部變量,內容都為null,所以 e.next = newTable[i]=null;
  • 第4步:newTable[i]=e={key:3,value:A};
  • 第5步:e=next={key:5,value:C};

循環結果如下,e={key:5,value:C},滿足while()循環條件,接著繼續!

圖片

第二次循環過程如下:

  • 第1步:此時 e 等于{key:5,value:C},取最新的鏈表結構,next=e.next={key:3,value:A};
  • 第2步:通過 key 重新 hash 計算得到下標 i = 3;
  • 第3步:在第一次循環中,newTable[i]已經插入值,所以 e.next = newTable[i]={key:3,value:A};
  • 第4步:newTable[i]=e={key:5,value:C};
  • 第5步:e=next={key:3,value:A};

循環結果如下,e={key:3,value:A},滿足while()循環條件,接著繼續!

第三次循環過程如下:

  • 第1步:此時 e 等于{key:3,value:A},取最新的鏈表結構,next=e.next=null;
  • 第2步:通過 key 重新 hash 計算得到下標 i = 3;
  • 第3步:在第二次循環中,newTable[i]已經插入值,所以 e.next = newTable[i]={key:5,value:C};
  • 第4步:newTable[i]=e={key:3,value:A};
  • 第5步:e=next=null;

循環結果如下,e=null,while()程序不在循環!

綜合線程1、線程2執行結果,最終 hashMap 的存儲結果,如下圖:

可以很清晰的看到,鏈表發生死循環了!

于是,當我們在遍歷 hashMap 鏈表內容的時候,就會出現上文中問題復現的場景,死循環式的輸出相同的內容,CPU 直接飆到200%了!

對于這種問題,當初有人上報到 SUN 公司,但是 SUN 不認為這是一個問題,因為 HashMap 本來就不支持并發操作!

所以,不建議在多線程環境下使用 HashMap,那如果要在多線程環境下使用 map 操作類,該怎么辦呢?

四、解決辦法

辦法肯定是有的,如果大家想在多線程場景下使用 HashMap,有兩種解決辦法:

  • 第一種,推薦使用并發包中的 ConcurrentHashMap 類,一種使用分段鎖的 hashMap 類,在之后的文章中,咱們也會介紹到它。
  • 另一種,是使用Collections.synchronizedMap(Mao<K,V> map)工具方法,將 HashMap 變成一個線程安全的 map,其實就是對 map 中的方法進行加鎖處理,保證多線程下操作安全!
責任編輯:趙寧寧 來源: Java極客技術
相關推薦

2022-03-21 11:50:58

醫療物聯網物聯網

2023-07-13 09:16:47

循環隊列指針front?

2023-11-10 08:22:09

雪花算法生成算法分布式

2016-01-27 10:26:53

JavaScript操作系統

2024-05-27 08:04:41

2016-01-26 15:33:07

JavaScriptNodeOS操作系統

2024-05-27 08:01:15

2022-09-29 08:39:37

架構

2024-05-07 09:04:39

2012-02-01 10:18:23

編程

2016-07-11 00:40:30

2024-07-18 20:18:51

2018-10-11 10:41:12

Go 開發技術

2018-09-28 07:00:03

編程語言Go語言

2020-09-29 06:39:38

智能

2022-05-09 08:40:14

Python技巧代碼

2020-11-16 12:09:25

Python開發工具

2020-10-09 07:54:43

PythonJava爬蟲

2021-06-07 09:55:58

JavaScript開發 技巧

2022-10-18 08:38:16

內存泄漏線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产xxxx在线 | 精品国产一区二区三区性色av | 91精品国产91久久久久久吃药 | 精品视频免费 | www.99热这里只有精品 | 成人国产精品免费观看 | 99精品国产一区二区三区 | 91日韩在线 | 草在线 | 国产午夜精品久久久 | 成人免费观看男女羞羞视频 | 国产精品久久av | 国产亚洲精品美女久久久久久久久久 | 久久综合一区二区 | 一级片在线观看 | 国产精品视频网站 | 国产成人精品a视频一区www | 国产免费av网 | 亚洲精品久久 | 99久久久99久久国产片鸭王 | 欧美日韩在线免费 | 国产电影一区二区在线观看 | 一区在线播放 | 日韩在线不卡视频 | 欧美精品成人一区二区三区四区 | 一区影院 | 亚洲另类视频 | 99精品久久久 | 欧美日韩亚洲一区 | 免费午夜电影 | 91精产国品一二三区 | 日本不卡高字幕在线2019 | 亚洲成av人片在线观看 | 黄在线 | 美女久久久 | 久久久网| 欧美在线一区二区三区 | 91视频www.| 国产精品69毛片高清亚洲 | 视频在线一区二区 | 国产精品永久久久久久久www |