簡體   English   中英

非遞歸互斥體所有權

[英]Non-recursive mutex ownership

我在SO上閱讀了這個答案

因為遞歸互斥鎖具有所有權感,所以獲取互斥鎖的線程必須與釋放互斥鎖的線程相同。 對於非遞歸互斥鎖,沒有所有權感,並且任何線程通常都可以釋放該互斥鎖,而不管最初使用哪個互斥鎖。

我對最后的發言感到困惑。 一個線程可以鎖定互斥鎖,而另一個線程可以解鎖該互斥鎖嗎? 我以為同一線程應該是唯一能夠解鎖互斥鎖的線程? 還是有任何特定的互斥鎖允許這樣做? 我希望有人可以澄清。

非遞歸互斥

大多數互斥鎖是(或至少應該是)非遞歸的。 互斥鎖是可以原子獲取或釋放的對象,它可以防止在多個線程之間共享的數據受到競爭條件,數據損壞和其他令人討厭的事情的影響。

單個互斥鎖只能由同一調用鏈中的單個線程獲取一次。 在相同的線程上下文中嘗試兩次獲取(或持有)相同的互斥鎖應該被視為無效方案,並且應該進行適當的處​​理(通常是通過ASSERT,因為您破壞了代碼的基本約定)。

遞歸互斥

這應該被視為代碼異味或駭客。 遞歸互斥鎖與標准互斥鎖唯一不同的唯一方法是,同一線程可以多次獲取遞歸互斥鎖。

需要遞歸互斥的根本原因是缺乏所有權,類別之間沒有明確的目的或界限。 例如,您的代碼可能會調用另一個類,然后再調用您的類。 然后,起始類可以嘗試再次獲取相同的互斥鎖,並且由於要避免崩潰,您可以將其實現為遞歸互斥鎖。

這種混亂不堪的類層次結構可能導致各種麻煩,而遞歸互斥僅為更基本的體系結構問題提供了創可貼解決方案。


無論互斥型的,它應該永遠是其獲取和釋放相同的互斥同一線程。 您在代碼中使用的一般模式如下所示:

Thread 1

    Acquire mutex A
    // Modify or read shared data
    Release mutex A

Thread 2

    Attempt to acquire mutex A
    Block as thread 1 has mutex A
    When thread 1 has released mutex A, acquire it
    // Modify or read shared data
    Release mutex A

當您具有可以同時獲取的多個互斥鎖(例如,互斥鎖A和B)時,情況將變得更加復雜。 您可能會遇到如下那樣的僵局:

Thread 1

    Acquire mutex A
    // Access some data...

*** Context switch to thread 2 ***

Thread 2

    Acquire mutex B
    // Access some data

*** Context switch to thread 1 ***

    Attempt to acquire mutex B
    Wait for thread 2 to release mutex B

*** Context switch to thread 2 ***

    Attempt to acquire mutex A
    Wait for thread 1 to release mutex A

*** DEADLOCK ***

現在,我們遇到一種情況,每個線程都在等待另一個線程釋放另一個鎖-這就是ABBA死鎖模式

為了避免這種情況,重要的是每個線程始終以相同的順序獲取互斥對象(例如,始終是A,然后是B)。

遞歸互斥鎖在設計上是特定於線程的(同一線程再次鎖定=遞歸,另一線程鎖定同時=塊)。 常規互斥鎖沒有這種設計,因此實際上它們可以在不同的線程中鎖定和解鎖。

我認為這涵蓋了您的所有問題。 直接從linux手冊頁獲取pthreads:

如果互斥鎖類型為PTHREAD_MUTEX_NORMAL,則不提供死鎖檢測。 嘗試重新鎖定互斥鎖會導致死鎖。 如果線程嘗試解鎖尚未鎖定的互斥鎖或已解鎖的互斥鎖,則會導致未定義的行為。

如果互斥鎖類型為PTHREAD_MUTEX_ERRORCHECK,則應提供錯誤檢查。 如果線程試圖重新鎖定已經鎖定的互斥鎖,則將返回錯誤。 如果線程試圖解鎖尚未鎖定的互斥鎖或已解鎖的互斥鎖,則將返回錯誤。

如果互斥鎖類型為PTHREAD_MUTEX_RECURSIVE,則該互斥鎖應保持鎖定計數的概念。 當線程首次成功獲取互斥量時,鎖定計數應設置為1。 每當線程重新鎖定此互斥鎖時,鎖定計數應增加一。 每當線程解鎖互斥鎖時,鎖計數應減一。 當鎖計數達到零時,互斥鎖將可供其他線程獲取。 如果線程試圖解鎖尚未鎖定的互斥鎖或已解鎖的互斥鎖,則將返回錯誤。

如果互斥鎖類型為PTHREAD_MUTEX_DEFAULT,則嘗試遞歸鎖定互斥鎖會導致未定義的行為。 如果未由調用線程鎖定互斥鎖,則嘗試對其進行解鎖會導致未定義的行為。 如果未鎖定互斥鎖,則嘗試對其進行解鎖會導致未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM