2012-01-09 29 views
5

我想知道什麼是使用可升級讀鎖,而不是執行這些步驟的優點:可升級的readlock的優點?

  1. 就拿讀鎖
  2. 檢查條件,看看我們是否需要採取寫鎖
  3. 發佈讀鎖定
  4. 就拿寫鎖定
  5. 進行更新
  6. 釋放寫鎖定
  7. 的執行上述步驟

一個明顯的缺點,而不是採取可升級讀鎖是,存在的時間的步驟3和4,在那裏另一個線程可能需要寫鎖定之間的窗口。

除了這個優點,你還發現在上面提到的步驟中採用可升級的讀鎖定的其他優點嗎?

+0

我敢打賭,這是可升級鎖的最大優勢,但我期待着其他意見。+1 – 2012-01-09 11:30:48

回答

6

讓我們考慮一下可以使用不具有單獨的「可升級閱讀器」的讀寫器鎖的不同方式。

使用圖案,有3及4正如你指出,在另一個線程可以採取的作家鎖之間的競爭。更重要的是,在3到4之間有一個步驟,一個線程可以採用寫入鎖定並更改我們在步驟2中觀察到的狀態

因此,我們有四個選擇取決於如何LIKEY這是發生:

  1. 我們留在你的做法,因爲這實際上是不可能(例如,一個給定的狀態轉換是單向的我們應用程序,所以一旦觀察它是永久性的)。在這種情況下,儘管我們很可能已經改造過,所以根本不需要鎖。 (單向轉換適合無鎖技術)。

  2. 我們只是把作家鎖定在第一位,因爲我們在步驟2中觀察到的狀態很可能會改變,並且使用讀卡器鎖定檢查它的時間會很浪費。

  3. 我們改變你的步驟:

    1. 就拿讀鎖
    2. 檢查條件,看看我們是否需要採取寫鎖
    3. 釋放讀鎖定
    4. 就拿寫鎖定
    5. 回覆 - 檢查條件是否改變。
    6. 進行更新
    7. 釋放寫鎖定
  4. 我們更改爲:

    1. 採取一個遞歸支撐鎖的讀鎖。
    2. 檢查我們是否需要寫入鎖定。
    3. 取寫鎖定(不釋放讀取)。
    4. 執行更新。
    5. 釋放寫入鎖定。
    6. 釋放讀取鎖定。

不難看出爲什麼4更誘人一些,雖然它只是稍微很難看到它是如何使死鎖容易創建。令人遺憾的是,稍微難一點的就足以讓很多人看到優點而不會看到缺點。

對於任何沒有發現它的人來說,如果兩個線程有​​讀鎖定,並且其中一個線程升級到寫鎖定,它必須等待另一個線程釋放讀鎖定。但是,如果第二個線程在不釋放讀鎖的情況下升級到寫鎖,那麼它將在第一個線程上永遠等待,永久等待它。


正如上面所說,只是哪種方法最好取決於它有多大的可能性爲國家在此期間(或如何及時,我們要對其做出反應,我想)改變。即使最後一種非釋放升級的方法可以在可行的代碼中佔據一席之地,只要有一個線程曾試圖升級其鎖而不釋放。

除了最後一個選項有效的特殊情況之外,其他選項之間的差別都與性能有關,哪個性能最高取決於重新檢查狀態的成本以及寫入中止的可能性由於其間的變化。

但是,請注意,它們都涉及到一個寫入鎖定,因此它們都具有阻止所有讀取線程的效果,即使寫入確實被中止。

可升級的讀鎖給了我們一箇中間地帶,因爲雖然它們阻止了寫鎖和其他可升級的讀鎖,但它們不會阻塞讀鎖。它們或許更好,但不是作爲可以升級的寫鎖,而是可以升級爲尚未寫入的寫鎖。*在決定不升級的情況下,對讀線程的影響爲零。

這意味着如果線程有可能決定不更改狀態,讀線程不會受到影響,並且性能改進可以證明它的用途。

*對於這個問題,「讀者 - 寫作者」有點用詞不當,我們可能會用ReaderWriterLockSlim保護整數或對象的數組,使用讀鎖來以原子方式讀取和寫入單個項目,並將寫鎖用於需要讀取整個數組而不使其部分在讀取時發生變化的操作。在這種情況下,它是一種閱讀操作,而不是需要排他鎖,而寫入操作對於共享鎖則沒有問題。

+0

感謝喬恩,非常好的觀點。 – Ngm 2012-01-11 05:49:07

0

它還可以防止可能發生的死鎖,因爲不同的線程同時運行,並且彼此等待釋放鎖。

+2

你能爲此提供一個例子嗎?我們也不能說我上面指出的步驟是一樣的嗎? – Ngm 2012-01-09 11:39:22

+0

升級鎖沒有您提到的競爭條件。 – linkerro 2012-01-09 13:44:41

+0

沒有競爭條件,因爲他們爭奪相同的資源(讓我們說r1),只有一個勝利,沒有死鎖。我沒有看到誰會防止死鎖? – Ngm 2012-01-10 06:37:03