2010-02-10 32 views
3

這是一個理論問題;我沒有真正需要解決的問題,我只是想了解這種方式背後的推理。爲什麼ReaderWriterLock在所有者線程終止時不會自動釋放/退出?

我發現,如果一個線程省略以退出ReaderWriterLock,那麼即使在原始線程終止後,其他線程也將無法獲得鎖。當擁有鎖的線程終止時,ReaderWriterLock不會將鎖授予等待的線程是否有充分的理由?

這是一個演示問題的測試案例。

static void Main(string[] args) 
    { 
     ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); 

     Thread t1 = new Thread((a) => 
     { 
      readerWriterLock.EnterReadLock(); 

      // this thread omits to Exit the lock.... 
     }); 

     Thread t2 = new Thread((a) => 
     { 
      readerWriterLock.EnterWriteLock(); 
     }); 

     t1.Start(); 
     t2.Start(); 

     // wait for all threads to finish 
     t1.Join(); 
     t2.Join(); 
    } 

回答

3

答案很簡單:有一個寫線程知道該讀線程已經終止,必須同時在鎖定操作昂貴沒有簡單的方法。

鎖通常作爲內存中的值來實現,因此獲取釋放鎖需要更改這些值。如果一個線程設置了獲取鎖的值,然後崩潰,獲得另一個鎖的唯一方法是如果你有一些後臺線程輪詢死鎖,查看它們最近獲取的鎖列表並清理它們。

除了昂貴且需要大量配管之外,它可能是不安全的,因爲您不知道線程墜毀前的確切距離。

+0

在一個線程崩潰的情況下,我同意假設它被鎖定的資源現在處於一個乾淨的狀態將是有風險的。但在正常線程終止的情況下,我認爲這樣的假設是安全的。關於性能,他們可以提供兩種實現:我們現在擁有的實現,以及實現自動發佈的更慢但更智能的實現。無論如何,謝謝你的回答,我認爲你解釋的確是這樣做的原因。 – Sylvain 2010-02-11 13:07:39

+1

回覆:正常的線程終止,你可以考慮使用RAII模式來鎖定,這有助於確保在退出某個範圍時釋放鎖定。在C#中,可以使用_lock_關鍵字(用於常規鎖)或_try/finally_ blocks(用於ReaderWriterLock)來確保在範圍退出時釋放鎖。再說一次,如果線程崩潰了,或者它調用了一些較低級別的線程退出函數,這不會對您有所幫助,但它將有助於降低編程錯誤導致死鎖的風險,因爲您忘記在某些複雜的代碼路徑上釋放鎖。 – 0xfe 2010-02-11 13:22:07

0

對於一個鎖來說,它可能不會太難以存儲專門保存它的線程的身份,或者是非專有的線程列表。然後鎖定代碼可以在它被阻止時週期性地檢查以查看是否有任何或全部阻塞它的線程仍然存在。這樣做的最大問題是線程沒有標準的方式來指示被鎖保護的實體處於合法狀態或無效狀態的時刻。如果持有鎖的線程在受保護的實體處於無效狀態時死亡,則應禁止訪問這些實體,除非或直到某些知道如何處理損壞的代碼已經這樣做。

相關問題