互斥鎖


簡介

在多工程式設計中,互斥鎖(也稱為互斥鎖)是用於防止多個執行緒或過程同時擁有共享資源的基本同步函式。“互斥”一詞表示“互斥”。

在本文中,我們將探討互斥鎖的元件、型別(包括示例)、用例以及實現示例。

什麼是互斥鎖?

互斥鎖透過限制可以同時獲取鎖的執行緒或程序數量來實現互斥。在訪問共享資源之前,單個執行緒或過程必須首先嚐試獲取該資源的互斥鎖。如果該鎖正被另一個執行緒或過程持有,則請求的執行緒或過程將被掛起並置於等待狀態,直到該鎖變為可用。在獲取鎖後,執行緒或過程可以訪問共享資源。完成後,它釋放該鎖,以便其他執行緒或過程可以獲取它。

互斥鎖的元件

下面我們討論互斥鎖的一些主要元件。

互斥變數 - 互斥變數用於表示鎖。它是一個數據結構,維護鎖的狀態並允許執行緒或程序獲取和釋放它。

鎖獲取 - 執行緒或程序可以透過請求來嘗試獲取鎖。如果鎖可用,則請求執行緒或程序將獲得鎖的所有權。否則,它將進入等待狀態,直到鎖可用。

鎖釋放 - 執行緒或過程完成使用共享資源後,它會釋放鎖,允許其他執行緒或程序獲取它。

互斥鎖的型別

互斥鎖有多種形式,提供不同級別的功能和行為。以下是幾種常用的互斥鎖型別:

遞迴互斥鎖

遞迴互斥鎖允許多次獲取鎖而不會阻塞作業系統或過程。它跟蹤之前獲取鎖的次數,並且需要相同次數的釋放才能完全解鎖。

示例

考慮一個數據結構,其中存在一個樹狀表示的檔案目錄結構。樹中的每個節點代表一個目錄,並且多個執行緒同時遍歷樹以執行不同的操作。使用遞迴互斥鎖可以防止衝突。一個執行緒遍歷一個目錄節點,獲取鎖,執行其操作,然後遞迴地獲取鎖以進入子目錄。遞迴互斥鎖允許多次獲取相同的鎖而不會阻塞執行緒,從而確保正確的遍歷和同步。

錯誤檢查互斥鎖

錯誤檢查互斥鎖在鎖操作期間執行額外的錯誤檢查。它透過防止迴圈鎖獲取來確保應用程式或過程不會獲取它當前已經持有的互斥鎖。

示例

考慮一個多執行緒程式,其中多個過程更新一個共享的公共計數器。該計數器由互斥鎖保護以避免衝突和競爭條件。如果一個執行緒意外地嘗試獲取它當前已經持有的互斥鎖,則會發生錯誤。錯誤檢查互斥鎖允許程式設計師檢測到此類編碼錯誤並快速修復。

定時互斥鎖

使用定時互斥鎖,演算法或過程可以在預定時間內嘗試獲取鎖。如果在分配的時間內鎖無法獲取,則獲取操作將失敗,並且執行緒/過程可以相應地做出反應。

示例

考慮一個即時系統,其中有多個操作或執行緒需要訪問有限數量的固定資源。每個任務都需要特定的資源才能完成。但是,如果任務無法在合理的時間內獲取所需的資源,則可能需要執行不同的操作或報告錯誤。透過使用定時互斥鎖,每個任務都可以嘗試在特定時間內獲取資源。如果在分配的時間內資源不可用,則根據超時情況,當前任務可以繼續使用備用方法或採取必要的措施。

優先順序繼承互斥鎖

優先順序繼承互斥鎖(也稱為優先順序上限互斥鎖)是一種特殊的互斥鎖,有助於減少優先順序反轉問題。當低優先順序執行緒或過程持有鎖,而高優先順序執行緒或過程需要該鎖時,優先順序繼承互斥鎖會臨時提升低優先順序執行緒的優先順序到等待釋放鎖的最高優先順序執行緒的優先順序。

示例

考慮一個即時系統,其中多個執行緒以不同的優先順序執行。這些過程可以訪問受互斥鎖保護的共享資源。優先順序繼承互斥鎖可用於避免優先順序反轉,優先順序反轉是指低優先順序執行緒透過持有鎖阻塞高優先順序執行緒的情況。互斥鎖透過臨時將低優先順序執行緒的優先順序提高到等待釋放鎖的最高優先順序執行緒的優先順序,來確保最高優先順序執行緒能夠立即訪問資源。

讀寫互斥鎖

讀寫鎖是一種同步機制,允許多個執行緒或過程同時訪問相同的資源,但在寫入操作期間在它們之間實施互斥,但它本身並不是互斥鎖的一個例項。

示例

在一個即時線上影片實現中,一個執行緒負責將新幀寫入給定的緩衝區,而多個執行緒同時讀取該緩衝區中的資料。可以使用讀寫鎖來允許同時讀取但保留寫入。多個讀取執行緒可以同時獲取讀鎖以無限制地訪問資料結構。但是,寫入執行緒僅在需要修改資料結構時獲取寫鎖,確保在更新期間沒有其他執行緒能夠讀取或寫入。

互斥鎖的用例

我們現在將討論互斥鎖的一些用例。

共享資源保護 - 互斥鎖通常用於在多執行緒或多程序環境中保護共享資源。它們確保一次只有一個執行緒或程序可以訪問共享資源,從而防止資料損壞和競爭條件。

臨界區 - 互斥鎖用於在程式中定義臨界區,一次只有一個執行緒可以在臨界區內執行程式碼。這確保了共享資料的完整性並防止併發訪問問題。

同步 - 互斥鎖允許執行緒或程序之間進行同步,使它們能夠以受控的方式協調其操作並訪問共享資源。它們確保某些操作以原子方式執行,避免衝突並確保一致性。

避免死鎖 - 互斥鎖可用於防止死鎖情況,在這種情況下,多個執行緒或程序無限期地等待彼此持有的資源。透過遵循正確的鎖定協議並避免迴圈依賴關係,可以避免死鎖情況。

示例

讓我們在下面探索一個在 Python 中實現互斥鎖的示例。

在這個示例中,建立了多個執行緒來將共享資源(shared_resource)增加 1。修改共享資源的關鍵部分受互斥鎖(mutex)保護。每個執行緒在進入關鍵部分之前獲取鎖,並在完成關鍵部分後釋放鎖。互斥鎖確保一次只有一個執行緒可以修改共享資源,防止出現競爭條件並確保最終結果的正確性。

import threading

# Shared resource
shared_resource = 0

# Mutex lock
mutex = threading.Lock()

# Function to increment the shared resource
def increment():
   global shared_resource
   for _ in range(100000):
      # Acquire the lock
      mutex.acquire()
        
      # Critical section
      shared_resource += 1
        
      # Release the lock
      mutex.release()

# Create multiple threads
threads = []
for _ in range(5):
   thread = threading.Thread(target=increment)
   threads.append(thread)
# Start the threads
for thread in threads:
   thread.start()

# Wait for all threads to complete
for thread in threads:
   thread.join()

# Print the final value of the shared resource
print("Shared Resource:", shared_resource)

輸出

Shared Resource: 500000

互斥鎖的優點

互斥鎖透過多種方式使多工處理受益:

  • 互斥 − 互斥鎖確保一次只有一個執行緒或程序可以持有鎖,防止出現競爭條件,並確保在多執行緒/多程序場景中具有可預測的行為。

  • 同步 − 互斥鎖允許程式和執行緒協調對共享資源的訪問,防止未經授權的訪問,並在應用程式或程序嘗試獲取已鎖定的互斥鎖時啟用受控訪問。

  • 簡單易移植 − 互斥鎖在各種程式語言和作業系統平臺上得到廣泛支援,並且相對易於使用。

  • 效率 − 互斥鎖通常在競爭較少的情況下執行良好,在鎖未被爭用時產生最小的開銷。

互斥鎖的缺點

互斥鎖透過多種方式對多工處理產生不利影響:

  • 潛在死鎖− 互斥鎖使用不當可能導致死鎖,多個執行緒或程序無限期地等待永遠不會釋放的鎖。

  • 優先順序反轉− 當高優先順序執行緒或程序被阻塞,等待低優先順序執行緒或程序持有的鎖時,可能會發生優先順序反轉。

  • 資源利用率− 如果執行緒或程序經常被阻塞以等待鎖,則互斥鎖可能導致資源利用率低下。

結論

總而言之,互斥鎖對於併發程式設計中基本功能的同步很有用。它們透過一次只允許單個執行緒或過程使用共享資源,從而實現互斥、同步並幫助防止競爭條件。互斥鎖提供了一種標準化的同步方法,易於操作且被廣泛接受。

更新於: 2023年7月17日

7K+ 瀏覽量

啟動您的 職業生涯

透過完成課程獲得認證

開始學習
廣告