2012-03-28 64 views
10

我使用ReaderWriterLockSlim與讀法和使用read方法來檢索要修改的元素的寫入方法的類。一個簡單的例子是:C#ReaderWriterLockSlim最佳實踐,以避免遞歸

class FooLocker 
{ 
    ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); 
    List<Foo> fooList = new List<Foo>(); 

    public void ChangeFoo(int index, string bar) 
    { 
     locker.EnterWriteLock(); 

     try 
     { 
      Foo foo = GetFoo(index); 
      foo.Bar = bar; 
     } 
     finally 
     { 
      locker.ExitWriteLock(); 
     } 
    } 

    public Foo GetFoo(int index) 
    { 
     locker.EnterReadLock(); //throws System.Threading.LockRecursionException 

     try 
     { 
      return fooList[index]; 
     } 
     finally 
     { 
      locker.ExitReadLock(); 
     } 
    } 

    //snipped code for adding instances etc. 
} 

如上所述,調用ChangeFoo()時候因爲寫鎖已經舉行,屆時GetFoo()嘗試進入一個讀鎖定這個代碼拋出一個LockRecursionException

我已經檢查了文檔ReaderWriterLockSlim,我可以使用LockRecursionPolicy.SupportsRecursion,使上述工作。但是,文檔還建議這不應該用於任何新的開發,只應在升級現有代碼時使用。

鑑於此,在寫入方法可以使用只讀方法檢索需要修改的內容的情況下,實現相同結果的最佳實踐是什麼?

+0

您是否嘗試通過讀取ReaderWriterLockSlim.IsReadLockHeld值來檢查讀取鎖是否被保留? http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.isreadlockheld.aspx – 2012-03-28 09:07:00

+0

設置SupportsRecursion不會是世界的盡頭,但Polity的anwer是更好的方法。 – 2012-03-28 09:13:55

回答

17

你可以把你的課分成暴露的方法和私人的內在方法。內部方法執行獲取邏輯和公共方法執行鎖定。例如:

class FooLocker 
{ 
    ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); 
    List<Foo> fooList = new List<Foo>(); 


    public void ChangeFoo(int index, string bar) 
    { 
     locker.EnterWriteLock(); 

     try 
     { 
      Foo foo = UnsafeGetFoo(index); 
      foo.Bar = bar; 
     } 
     finally 
     { 
      locker.ExitWriteLock(); 
     } 
    } 

    public Foo GetFoo(int index) 
    { 
     locker.EnterReadLock(); //throws System.Threading.LockRecursionException 

     try 
     { 
     return UnsafeGetFoo(index); 
     } 
     finally 
     { 
      locker.ExitReadLock(); 
     } 
    } 

    private Foo UnsafeGetFoo(int index) 
    { 
     return fooList[index]; 
    } 
} 
+1

很好的答案,謝謝!只需要確保私人不安全的方法有足夠的文件,以確保沒有確保沒有鎖定就沒有人使用它。 – 2012-03-28 09:34:57

+1

@AdamRodger文件和做'System.Diagnostics.Debug.Assert(locker.IsReadLockHeld || locker.IsUpgradableReadLockHeld)' – 2015-08-13 14:32:11

+0

我不明白有什麼區別,你剛搬到在try代碼的方法,爲什麼它物? – shinzou 2017-11-11 16:07:50