Dot-Net
檢查目前執行緒是否擁有鎖
假設我有以下程式碼:
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 塊,它們不是免費的)可能不值得。