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

從 Java 鎖到分布式鎖

開發 后端 分布式
在并發編程中常用到 synchronized 以及 ReentrantLock 鎖,在業務開發過程中也可能會用到分布式鎖,分布式鎖常用框架的就是基于 Redis 實現的分布式鎖框架 Redisson 和 基于 Zookeeper 實現的分布式鎖框架 Curator。當然,也有其他的鎖實現方式,在這里不做介紹。

 [[436819]]

前言

在并發編程中常用到 synchronized 以及 ReentrantLock 鎖,在業務開發過程中也可能會用到分布式鎖,分布式鎖常用框架的就是基于 Redis 實現的分布式鎖框架 Redisson 和 基于 Zookeeper 實現的分布式鎖框架 Curator。當然,也有其他的鎖實現方式,在這里不做介紹。

本文主要是在學習 Java 鎖以及分布式鎖的源碼后,做出的歸納總結。

1鎖的最基本要素

為什么要使用鎖?

關于為什么要使用鎖這個問題,答案顯而易見:“為了避免多線程并發沖突”。

在多線程中對公共數據的修改,必須要保證只有線程在進行操作。這里的公共數據可以是公共變量,也可以是數據庫中的一行數據。

鎖的基本要素

知道為什么要加鎖之后,就可以得出加鎖的基本要素:

  • 鎖標志:怎么樣才算加鎖成功?
  • 鎖持有者:是哪個線程加的鎖?
  • 鎖重入:自己加了鎖之后,再次加鎖?
  • 鎖并發:并發加鎖失敗的線程該怎么辦?
  • 鎖釋放:用完鎖,該怎么釋放?

簡單來說應該就是這些要素,遺漏之處,歡迎補充。

2加鎖標志

加鎖標志,就是需要一個標志來表示是否加鎖成功,并且這個加鎖標志要保證原子性。

  • synchronized 底層是 C++ 實現的,在 ObjectMonitor 對象中有一個 _count 參數用來標識是否持有鎖。
  • ReentrantLock 基于 AQS 實現,其中 state 表示線程是否持有鎖。ReentrantReadWriteLock 同樣基于 AQS 實現,其中 state 高 16 位表示讀鎖,低 16 位表示寫鎖。
  • Redisson 是基于 Redis 的 Hash 數據結構實現的,其中加鎖 key 是否存在,可以表示是否加鎖。
  • Curator 基于 ZooKeeper 臨時順序節點實現,判斷加鎖路徑下是否存在該節點,來表示是否加鎖。

3鎖持有者

  • 鎖持有者,肯定是當前線程,但是在分布式鎖中還需要加上機器,用來防止服務之間的線程沖突。
  • synchronized 在 ObjectMonitor 對象中 _owner 是指獲得鎖的線程。
  • ReentrantLock 和 ReentrantReadWriteLock 是在 AQS 的 Node 節點中有 Thread 對象,用來表示獲得鎖的線程。
  • Redisson 在 Hash 數據結構的 field 字段存放的是 UUID:ThreadId,從而保證在多個服務實例時防止并發沖突。
  • Curator 創建的臨時順序節點包含 UUID,表示加鎖機器,結構比如 /locks/lock_01/_c_UUID-lock-0000000000。

4鎖重入

當獲得鎖的線程再次嘗試獲取鎖的時候,保證需要計數。

  • synchronized 會對 _count 進行累加,CAS 更新。
  • ReentrantLock 會對 AQS 的 state 進行累加,CAS 更新。
  • Redisson 使用 Lua 腳本,對 Hash 結構的 value 進行累加。
  • Curator 是在 Java 代碼中維護了一個 AtomicInteger 類型的 lockCount 字段,用來表示重入。

5鎖等待

  • synchronized 并發加鎖失敗線程會自旋等待,涉及到偏向鎖、輕量級鎖、重量級鎖的鎖升級流程。
  1. 剛開始是無鎖的
  2. 偏向鎖:一段同步代碼一直被一個線程訪問,這個線程自動獲取鎖,大多數都是由同一個線程獲取鎖,這就會出現偏向鎖。目的是只有一個線程執行同步代碼塊時提高性能,JDK 6 后在 JVM 中默認開啟。對象頭標志位(01-無鎖) 是否偏向鎖標志(1-是偏向鎖)
  3. 輕量級鎖:鎖是偏向鎖時,被其他線程訪問,偏向鎖就升級為輕量級鎖,其他線程通過自旋形式嘗試獲取鎖 對象頭標志位 00
  4. 重量級鎖:只有一個線程等待,該線程是在自旋等待獲取鎖。當自旋一定次數或者一個持有鎖一個自旋時來了第三個線程,就會升級為重量級鎖。對象頭標志位 10
  • ReentrantLock 會放到 AQS 雙向同步隊列中,監聽上一個節點是否為虛擬頭結點,是則嘗試獲取鎖。
    • 非公平鎖新線程會默認參加搶鎖,公平鎖會先查看隊列是否為空。
    • 自旋等待時會使用 LockSupport.park() 方法,這時候會讓出 CPU 資源,其他線程會調用 LockSupport.unpark()。
    • 可以使用 tryLock 方法設置時間,在指定時間內獲取鎖失敗或者被中斷,則會返回加鎖失敗。
  • Redisson 并發加鎖,失敗線程會獲取到當前鎖的超時時間,然后通過 Semaphore tryAcquire 方法阻塞一定時間后,再次嘗試獲取鎖。
    • 公平鎖會額外使用 Redis 的 List 數據結構來當做線程等待隊列,使用 sorted set 有序集合數據結構來存放等待線程的順序(score 是超時時間戳)。
  • Curator 并發加鎖會直接創建臨時順序節點,然后監聽順序節點中自己的上一個節點(防止羊群效應),默認是公平鎖。

6鎖釋放

  • synchronized 不需要手動釋放。
  • ReentrantLock 對 state 遞減為 0 后,喚醒后續節點,有后續節點需要調用 LockSupport.unpark(s.thread)。
  • Redisson 主動釋放直接刪除 key 即可。超時釋放即服務宕機,沒有看門狗續租了,指定時間后,Redis Key 就會被自動釋放。
  • Curator 主動釋放會刪除節點,如果服務宕機了,節點會被自動刪除。

7總結

本文從多個角度總結分析了鎖和分布式鎖的基本要素,同樣基于 MySQL 等數據庫的鎖可以參考實現。

 本文轉載自微信公眾號「程序員小航」,可以通過以下二維碼關注。轉載本文請聯系程序員小航公眾號。

 

責任編輯:武曉燕 來源: 程序員小航
相關推薦

2018-11-27 16:17:13

分布式Tomcat

2019-06-19 15:40:06

分布式鎖RedisJava

2021-07-06 08:37:29

Redisson分布式

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2021-07-16 07:57:34

ZooKeeperCurator源碼

2022-08-04 08:45:50

Redisson分布式鎖工具

2021-07-02 08:51:09

Redisson分布式鎖公平鎖

2021-06-30 14:56:12

Redisson分布式公平鎖

2020-10-19 07:30:57

Java Redis 開發

2023-08-21 19:10:34

Redis分布式

2023-09-22 08:00:00

分布式鎖Redis

2017-10-24 11:28:23

Zookeeper分布式鎖架構

2022-01-06 10:58:07

Redis數據分布式鎖

2021-10-25 10:21:59

ZK分布式鎖ZooKeeper

2018-07-17 08:14:22

分布式分布式鎖方位

2021-04-29 19:07:33

Redis演進微服務

2024-11-28 15:11:28

2021-07-01 09:42:08

Redisson分布式

2024-12-11 12:41:33

2024-10-07 10:07:31

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品一区二 | 久久av综合 | 黄色毛片免费看 | 免费三级网 | 国产一区在线视频 | 欧美日韩精品免费 | 粉嫩粉嫩芽的虎白女18在线视频 | 精品一区视频 | 亚洲国产中文字幕 | 九色.com| 亚洲精品一区二区三区蜜桃久 | av色在线 | 女同久久| 欧美二区三区 | 一区欧美 | 国产精品一区二区精品 | 成年免费大片黄在线观看一级 | 中文在线日韩 | 免费一区二区三区在线视频 | 国内91在线| 国产成年人小视频 | 欧美日韩视频在线播放 | 久久蜜桃av一区二区天堂 | 国产精品色 | 欧美中文一区 | 国内自拍偷拍视频 | 亚洲啪啪一区 | 日本黄色一级视频 | 久久久涩 | 在线只有精品 | 国产免费一二三区 | 91p在线观看| 中文字幕啪啪 | 视频在线观看一区 | 国产激情视频网址 | 成人福利在线观看 | 91精品国产综合久久久久久首页 | 高清视频一区二区三区 | 成av在线 | 中文字幕专区 | 成人在线看片 |