一文看懂臨界區、互斥鎖、同步鎖、臨界區、訊號量、自旋鎖等名詞!
點選上方“業餘草”,選擇“置頂公眾號”
第一時間獲取技術乾貨和業界資訊!
關於執行緒安全的專有名詞有一大堆。你們突然之間問我這個名詞是什麼意思,那個名詞是什麼意思我還真不一定能給你準確的回答。這還別說一門語言一堆名詞。其實有些名詞叫法不同,實際上就是一個意思。
A 語言有這個名詞,B 語言就起另外一個名詞。不能大膽的雷同,所以就改變一個叫法,其本質還是一樣的。
為了減少大家在私信我,那我今天就來扯一扯,競態條件,競態資源,輪詢忙等,鎖變數,原子性,TSL,阻塞,睡眠,喚醒,管程,互斥鎖,同步鎖,臨界區,互斥量,訊號量,自旋鎖等各個專業名詞的實際所代表的含義。
競態條件:多執行緒的核心矛盾是“競態條件”,即多個執行緒同時讀寫某個欄位。
競態資源:競態條件下多執行緒爭搶的是“競態資源”。
臨界區:涉及讀寫竟態資源的程式碼片段叫“臨界區”。
互斥:保證竟態資源安全的最樸素的一個思路就是讓臨界區程式碼“互斥”,即同一時刻最多隻能有一個執行緒進入臨界區。
最樸素的互斥手段:在進入臨界區之前,用if檢查一個bool值,條件不滿足就“忙等”。這叫“鎖變數”。但鎖變數不是執行緒安全的。因為“檢查-佔鎖”這個動作不具備“原子性”。
TSL:“TSL指令”就是原子性地完成“檢查-佔鎖”的動作。
自旋鎖:就算不用TSL指令,也可以設計出執行緒安全的程式碼,有一種既巧妙又簡潔的結構叫“自旋鎖”。當然還有其他更復雜的鎖比如“Peterson鎖”。
忙等待:但自旋鎖的缺點是條件不滿足時會“忙等待”,需要後臺排程器重新分配時間片,效率低。
解決忙等待問題的是:“sleep”和“wakeup”兩個原語。sleep阻塞當前執行緒的同時不會讓出它佔用的鎖。wakeup可以喚醒在目標鎖上睡眠的執行緒。
互斥量:使用sleep和wakeup原語,保證同一時刻只有一個執行緒進入臨界區程式碼片段的鎖叫“互斥量”。
訊號量:把互斥鎖推廣到"N"的空間,同時允許有N個執行緒進入臨界區的鎖叫“訊號量”。互斥量和訊號量的實現都依賴TSL指令保證“檢查-佔鎖”動作的原子性。
管程:把互斥量交給程式設計師使用太危險,有些程式語言實現了“管程”的特性,從編譯器的層面保證了臨界區的互斥,比如Java的synchronized關鍵字。
互斥鎖、獨佔鎖、內建鎖:並沒有“同步鎖”這個名詞,Java的synchronized正確的叫法應該是“互斥鎖”,“獨佔鎖”或者“內建鎖”。但有的人“顧名思義”叫它同步鎖。
下面我們簡單的來擴充套件一下。比如下面的程式:
多執行緒同時執行這段程式碼可能就會出錯。當兩個執行緒競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。導致競態條件發生的程式碼區稱作臨界區。上例中 add() 方法就是一個臨界區,它會產生競態條件。在臨界區中使用適當的同步就可以避免競態條件。
上面程式碼中 occupied 就是鎖變數。
自旋鎖的關鍵就是用一個 while 輪詢,代替 if 檢查狀態,這樣就算執行緒切出去,另一個執行緒也因為條件不滿足迴圈忙等,不會進入臨界區。這是一個非常常用的結構,不光用在自旋鎖,基本是使用條件變數 wait(),notifyAll() 時候的一種慣用法。
自旋鎖的缺點是迴圈忙等。如果併發的執行緒不像程式排程那樣在時間片用完以後會自動切換上下文,就會形成死鎖。所以最好在條件不滿足的時候,讓出執行緒的控制權,讓其他執行緒有機會執行來使條件滿足。
執行緒安全不管搞出多少名詞,都逃不出 3 大核心:原子性、可見性、有序性。推薦閱讀《Java 執行緒安全的3大核心:原子性、可見性、有序性》,其他的相關鎖知識,請檢視我公眾號裡的相關文章。
原文連結:https://www.xttblog.com/?p=3865
10T技術資源大放送!包括但不限於:C/C++,Linux,Python,Java,PHP,人工智慧,GO等等。在公眾號內回覆對應關鍵字或框架名字,即可免費獲取!!
你再主動一點點 我們就有故事了
相關文章
- 同步篇——臨界區與自旋鎖
- JMH模擬鎖高爭用,長臨界區,測試鎖效能
- 併發程式設計之臨界區\阻塞\非阻塞\死鎖\飢餓\活鎖程式設計
- Jtti:linux下訊號量和互斥鎖有哪些區別?JttiLinux
- C 語言的 互斥鎖、自旋鎖、原子操作
- 執行緒同步(windows平臺):臨界區執行緒Windows
- 執行緒安全: 互斥鎖和自旋鎖(10種)執行緒
- 作業系統 訊號量vs互斥鎖作業系統
- Java 中15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖,樂觀鎖,分段鎖,自旋鎖等等Java
- java 中的鎖 -- 偏向鎖、輕量級鎖、自旋鎖、重量級鎖Java
- ZooKeeper 分散式鎖 Curator 原始碼 04:分散式訊號量和互斥鎖分散式原始碼
- InnoDB常用鎖總結(行鎖、間隙鎖、臨鍵鎖、表鎖)
- 一句話擼完重量級鎖、自旋鎖、輕量級鎖、偏向鎖、悲觀、樂觀鎖等各種鎖
- 互斥鎖和訊號量有什麼不同?(譯)
- MySQL 行級鎖之 間隙鎖、臨鍵鎖MySql
- 面試官:你說說互斥鎖、自旋鎖、讀寫鎖、悲觀鎖、樂觀鎖的應用場景面試
- 執行緒同步與互斥:互斥鎖執行緒
- MySQL記錄鎖、間隙鎖、臨鍵鎖小案例演示MySql
- Java併發基礎-鎖的使用及原理(可重入鎖、讀寫鎖、內建鎖、訊號量等)Java
- 自旋鎖spinlock
- 自旋鎖、阻塞鎖、可重入鎖、悲觀鎖、樂觀鎖、讀寫鎖、偏向所、輕量級鎖、重量級鎖、鎖膨脹、物件鎖和類鎖物件
- Concurrency(三:競態條件和臨界區)
- 一文讀懂原子操作、記憶體屏障、鎖(偏向鎖、輕量級鎖、重量級鎖、自旋鎖)、Disruptor、Go Context之上半部分記憶體GoContext
- 透過互斥鎖+條件量的方式實現同步與互斥
- Linux核心自旋鎖Linux
- 詳解 MySql InnoDB 中的三種行鎖(記錄鎖、間隙鎖與臨鍵鎖)MySql
- 【go】golang中鎖的用法-互斥鎖Golang
- 一文看懂Java鎖機制Java
- LiteOS:SpinLock自旋鎖及LockDep死鎖檢測
- liteos互斥鎖(七)
- 原子鎖和普通鎖的區別
- 讀寫鎖 ReentrantReadWriteLock 與 互斥鎖 的效率
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等...Java
- Java 種15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖等等Java
- Go 語言的原子操作和互斥鎖的區別Go
- 從自旋鎖、睡眠鎖、讀寫鎖到 Linux RCU 機制講解Linux
- 解決多執行緒競爭條件——臨界區執行緒
- 圖解程式執行緒、互斥鎖與訊號量-看完不懂你來打我圖解執行緒