C#我移植了一些遺留代碼,發現一些類有如下鎖定對象:鎖定在使用Environment.TickCount
protected readonly object _stateLock = Environment.TickCount;
沒有任何優勢,這在新的對象()? 傳來傳去另一個鎖定對象我看到的是
private Nullable<int> _sLock = new Nullable<int>(Environment.TickCount);
任何優勢,使用這個?
C#我移植了一些遺留代碼,發現一些類有如下鎖定對象:鎖定在使用Environment.TickCount
protected readonly object _stateLock = Environment.TickCount;
沒有任何優勢,這在新的對象()? 傳來傳去另一個鎖定對象我看到的是
private Nullable<int> _sLock = new Nullable<int>(Environment.TickCount);
任何優勢,使用這個?
不,沒有任何優勢。 Environment.TickCount
和Nullable<int>
值都是值類型,並將被裝箱,即包裝在新的object
參考中。
代碼的第二個版本實際上更糟糕。第一個,使用TickCount
,僅僅是分配新的object
參考的低效方法。但引用永遠不會改變,否則鎖定會正常工作。 lock
聲明(或更確切地說,底層的Monitor
類)完全不關心對象內的值是什麼;它所關心的只是參考本身。所以拳擊TickCount
或17
或只是創建一個新的object
,都是一樣的。
第二個版本,其中使用Nullable<int>
只是明顯錯誤,並且根本不會實現鎖定行爲。因爲Nullable<int>
本身就是一個值類型,所以當任何代碼試圖鎖定該值時(即lock (_sLock)
),該值將在該時間點被裝箱,爲該鎖創建一個全新的object
引用。只有在每個需要共享數據的代碼的關鍵部分也使用相同的object
參考進行鎖定時,鎖才起作用。由於他們都將獲得自己的新參考,所以根本不會發生同步。
我還應該指出,編譯器通常不會允許您執行第二個版本。即如果你試圖編譯這段代碼,它會失敗與錯誤:
Nullable<int> _sLock;
lock (_sLock) { }
錯誤會讀
error CS0185: 'int?' is not a reference type as required by the lock statement
如果你確實有像你說的代碼的地方寫的,那麼是誰寫它的人繞過這個非常有用的編譯器錯誤,通過強制執行_sLock
值,例如是這樣的:
lock ((object)_sLock) { }
如果我看到這樣的代碼,我會立即懷疑是誰寫它的人的能力,並會堅持審查他們感動的應該是線程安全的任何代碼,看什麼否則他們搞砸了。
我無法想象鎖定盒裝int的任何優勢。誰寫的可能只是忽略了創建鎖對象的簡單方法,一個簡單的'new object()'。 –
第二個片段的唯一優點是你永遠不會遇到死鎖。 * lock *語句必須包含它並始終生成一個唯一對象。當然,你永遠不會得到工作鎖。這位程序員不知道他在做什麼。 –