Dot-Net

檢查目前執行緒是否擁有鎖

  • August 8, 2019

假設我有以下程式碼:

public class SomeClass()
{
   private readonly object _lock = new object();

   public void SomeMethodA()
   {
       lock (_lock)
       {
           SomeHelperMethod();

           //do something that requires lock on _lock
       }
   }

   public void SomeMethodB()
   {
       lock (_lock)
       {
           SomeHelperMethod();

           //do something that requires lock on _lock
       }
   }

   private void SomeHelperMethod()
   {
       lock (_lock)
       {
           //do something that requires lock on _lock
       }
   }
}

鎖定內部SomeHelperMethod似乎是多餘和浪費的,因為所有呼叫者都已經鎖定了。然而,簡單地移除鎖SomeHelperMethod似乎很危險,因為我們以後可能會重構程式碼並忘記_lock在呼叫之前鎖定對象SomeHelperMethod

理想情況下,我可以通過斷言目前執行緒在_lockinside上擁有一個鎖來解決這個問題SomeHelperMethod

private void SomeHelperMethod()
{
   Debug.Assert(Monitor.HasLock(_lock));

   //do something that requires lock on _lock
}

但似乎沒有這樣的方法。Monitor.TryEnter沒有幫助,因為鎖是可重入的。因此,如果目前執行緒已經擁有鎖,TryEnter仍然會成功並返回true。唯一會失敗的情況是另一個執行緒擁有鎖並且呼叫超時。

那麼,這樣的方法存在嗎?如果不是,為什麼?對我來說這似乎並不危險,因為它只是告訴您目前執行緒(而不是另一個執行緒)是否擁有鎖。

這在 .NET 4.5 中使用Monitor.IsEntered(object).

鎖定或重新鎖定實際上是免費的。這種低成本的缺點是您沒有其他同步機制那麼多的功能。就像您在上面所說的那樣,只要鎖定至關重要,我就會簡單地鎖定。

如果您非常想省略“不必要的”鎖而不冒潛在重構的風險,請添加註釋。如果有人更改了您的程式碼並且它中斷了,那裡有一條註釋來解釋原因。如果他們仍然無法弄清楚,那是他們的問題,而不是你的問題。另一種選擇是創建一個用作鎖定對象的類,該對象包含一個可以打開和關閉的布爾值。但是,這樣做帶來的成本(包括 try/finally 塊,它們不是免費的)可能不值得。

引用自:https://stackoverflow.com/questions/496388