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

讀寫鎖 + HashMap 超級組合,真心推薦!

開發 前端
很多同學問我:”勇哥,假如讀鎖申請成功后,寫鎖會阻塞嗎 ?“ 或者 ”寫鎖申請成功后,讀鎖會被阻塞嗎?“ 。答案是肯定的,讀寫必然互斥 。

這篇文章,我們深入聊聊:讀寫鎖如何保證 HashMap 成為一個線程安全的容器。

圖片圖片

1.編程范式例子

圖片圖片

上圖展示了使用讀寫鎖對 HashMap 進行操作的編程范式,核心要點:

  • 單獨的類用于封裝對 HashMap 的讀、寫操作;
  • 讀操作方法內部,先獲取讀鎖,讀取數據之后,釋放讀鎖;
  • 寫操作方法內部,先獲取寫鎖,寫入成功之后,釋放寫鎖。

很多同學問我:”勇哥,假如讀鎖申請成功后,寫鎖會阻塞嗎 ?“ 或者 ”寫鎖申請成功后,讀鎖會被阻塞嗎?“ 。

答案是肯定的,讀寫必然互斥 。

筆者分別寫兩個簡單的例子,并展示堆棧圖,大家就可以一目了然。

2.讀鎖申請成功后,寫鎖會被阻塞

我們將 ReadWriteLockCache 的讀操作修改如下:

圖片圖片

然后編寫 main 方法:

圖片圖片

main 方法中,我們先后啟動讀線程、寫線程 。

圖片圖片

我們通過 IDEA 打印堆棧日志,發現:讀線程先獲取讀鎖,然后休眠 10 秒,這樣讀鎖就不會釋放,后面寫線程嘗試獲取寫鎖時,寫線程阻塞了。

3.寫鎖申請成功后,讀鎖會被阻塞

我們將 ReadWriteLockCache 的讀操作代碼還原,然后將寫操作修改如下:

圖片圖片

然后編寫 Main 方法:

圖片圖片

main 方法中,我們先后啟動寫線程、讀線程 。

圖片圖片

我們通過 IDEA 打印堆棧日志,發現:寫線程先獲取寫鎖,然后休眠 10 秒,這樣寫鎖就不會釋放,后面讀線程嘗試獲取讀鎖時,線程阻塞了。

4.使用 ConcurrentHashMap 是不是更簡單點

有的同學會問:使用 ConcurrentHashMap 是不是更簡單點嗎 ?

我們分兩個層面來說明:

1)讀寫鎖 + 多個 HashMap

讀寫鎖可以操作多個 HashMap ,每次寫操作需要同時變更多個 HashMap ,為了保證其一致性,故需要加鎖,ConcurrentHashMap 并發容器在多線程環境下的線程安全也只是針對其自身,故從這個維度,選用讀寫鎖是必然的選擇 。

我們舉 RocketMQ NameServer 的經典案例:

Broker 啟動之后會向所有 NameServer 定期(每 30s)發送心跳包(路由信息),NameServer 會定期掃描 Broker 存活列表,如果超過 120s 沒有心跳則移除此 Broker 相關信息,代表下線。

那么 NameServer 如何保存路由信息呢?

圖片圖片

路由信息通過幾個 HashMap 來保存,當 Broker 向 Nameserver 發送心跳包(路由信息),Nameserver 需要對 HashMap 進行數據更新,但我們都知道 HashMap 并不是線程安全的,高并發場景下,容易出現 CPU 100% 問題,所以更新 HashMap 時需要加鎖,RocketMQ 使用了  JDK 的讀寫鎖 ReentrantReadWriteLock 。

  • 更新路由信息,操作寫鎖

圖片圖片

  • 查詢主題信息,操作讀鎖

圖片圖片

2)讀寫鎖 + 1 個 HashMap

假如我們僅僅使用讀寫鎖操作 1 個 HashMap ,那么我們需要分析下 ConcurrentHashMap 的原理。

  • JDK 8 之前

圖片圖片

從圖中我們可以看出, ConcurrentHashMap 內部進行了 Segment 分段,Segment 繼承了 ReentrantLock,可以理解為一把鎖,各個 Segment 之間都是相互獨立上鎖的,互不影響。

同一個 Segment 的讀寫都需要加鎖,即落在同一個 Segment 中的讀、寫操作是串行的,其讀的并發性低于讀寫鎖 + HashMap 的,

因此在 JDK 1.8 之前,ConcurrentHashMap 是落后于讀寫鎖 + HashMap 的結構的

  •  JDK 1.8 及其后續版本

圖片圖片

JDK 1.8 對 ConcurrentHashMap 代碼進行了大幅優化,存儲結構與 HashMap 非常類似,同時引入了 CAS 機制(輕量級) 來解決并發更新。

因此,相比讀寫鎖操作 1 個 HashMap, 使用 ConcurrentHashMap 更具性能優勢。

5.總結

這篇文章,我們深入剖析:讀寫鎖如何保證 HashMap 成為一個線程安全的容器

1)讀寫鎖編程范式

  • 單獨的類用于封裝對 HashMap 的讀、寫操作;
  • 讀操作方法內部,先獲取讀鎖,讀取數據之后,釋放讀鎖;
  • 寫操作方法內部,先獲取寫鎖,寫入成功之后,釋放寫鎖。

2)兩個實驗例子

  • 讀鎖申請成功后,寫線程申請寫鎖會阻塞
  • 寫鎖申請成功后,讀線程申請讀鎖會阻塞

我們用兩個實驗突出了讀寫鎖的特性:讀讀不互斥,讀寫互斥,寫寫互斥 。

3)使用 ConcurrentHashMap 是不是更簡單點

  • 假如需要操作 多個 HashMap ,那么讀寫鎖更加有優勢 ;
  • 假如僅僅操作 1個 HashMap  ,  建議使用  JDK 1.8 ConcurrentHashMap ,性能會更好。
責任編輯:武曉燕 來源: 勇哥Java實戰
相關推薦

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫鎖

2024-05-15 09:41:22

樂觀鎖編程

2019-11-28 16:00:06

重入鎖讀寫鎖樂觀鎖

2023-03-10 15:45:03

Golang公平鎖

2013-06-06 13:10:44

HashMap無鎖

2024-06-11 00:01:00

并發validate場景

2021-07-06 08:37:29

Redisson分布式

2018-01-01 05:23:13

服務化讀寫分離架構

2022-02-14 15:07:48

進程FileChanne線程

2024-10-10 09:40:29

2020-09-26 23:09:00

Linux系統編程讀寫鎖

2023-01-04 13:43:24

讀寫鎖AQS共享模式

2023-06-02 08:29:24

https://wwMutex

2025-01-09 06:00:00

Checkmate監控系統開源

2025-05-09 08:40:00

WAF開源網站防護墻

2025-04-16 11:20:59

2025-05-16 02:00:00

HashMapJava代碼

2020-09-16 07:56:28

多線程讀寫鎖悲觀鎖

2021-12-16 18:38:13

面試Synchronize

2024-08-12 17:36:54

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99精品视频一区二区三区 | 天堂成人国产精品一区 | 午夜精品在线 | 精品亚洲91 | 一区在线播放 | 玖玖玖av| 久久精品国产免费看久久精品 | 成人午夜网站 | 自拍 亚洲 欧美 老师 丝袜 | 成人在线精品 | 久久精品国产亚洲一区二区 | 国产久 | 毛片网站在线观看视频 | 国产福利91精品一区二区三区 | 成人午夜网站 | 国产精品美女久久久久aⅴ国产馆 | 国产精品1区| 中文一区| 男人天堂99 | 欧美日韩在线一区二区三区 | 日本一区二区不卡视频 | 毛片电影 | 白浆在线| 日韩一区二区免费视频 | 韩国理论电影在线 | 91久久精品国产91久久 | 国产精品视频免费观看 | 欧美成人专区 | 亚洲视频免费在线观看 | 国产精品成人免费 | 欧美一区二区在线视频 | 国产成人小视频 | 亚洲成年人免费网站 | 成人av在线网站 | 超碰人人91| 成人在线视频免费播放 | 中文在线观看视频 | 色资源在线视频 | 国产一区二区在线观看视频 | 亚av在线| 日本特黄特色aaa大片免费 |