13.4 对锁和字段风格的事件的微小改变
13.4.1 健壯的鎖
1 class Program 2 { 3 static object locker = new object(); 4 static void Main(string[] args) 5 { 6 List<string> list = new List<string>(); 7 lock (locker) 8 { 9 list.Add("item"); 10 } 11 12 //在C# 4之前——包括使用C# 4處理.NET 4之前的東西時——以上語句將被有效地編譯為下面 的代碼: 13 14 object tmp = locker; 15 Monitor.Enter(tmp); 16 try 17 { 18 list.Add("item"); 19 } 20 finally 21 { 22 Monitor.Exit(tmp); 23 } 24 } 25 }這沒有問題,并且它還避免了一些問題。我們要確保釋放的監(jiān)視器與獲取的是同一個,因此
首先將被鎖定內(nèi)容的引用復(fù)制到一個臨時局部變量內(nèi) 。這同時意味著鎖的表達(dá)式只會進(jìn)行一
次求值。然后我們在 try 語句塊之前獲取鎖。因此如果獲取鎖的線程異常終止,則不會執(zhí)行
finally 塊中釋放鎖的語句。這還將導(dǎo)致另一個問題:如果線程在獲取鎖之后和進(jìn)入 try 塊之前
異常終止,我們也無法釋放鎖。這可能會導(dǎo)致死鎖——其他線程將一直等待該線程釋放鎖。盡管
CLR一直以來都在努力阻止類似事情發(fā)生,但也不是完全沒有可能發(fā)生。
我們所需要的,是一種原子地獲取鎖并知道它已經(jīng)被獲取的方式。幸運(yùn)的是,.NET 4新增加
了 Monitor.Enter 的重載,C# 4的編譯器將使用這種方式:
13.4.2 字段風(fēng)格的事件
值得簡單一提的是,C# 4對字段風(fēng)格事件的實現(xiàn)方式作了兩處修改。盡管它們是潛在的破壞性更改,但似乎不會對你產(chǎn)生什么影響。
總之,字段風(fēng)格的事件像字段一樣進(jìn)行聲明,不再包含顯式的 add/remove 語句塊,如下:
首先,線程安全的實現(xiàn)方式發(fā)生了改變。在C# 4之前,字段風(fēng)格的事件生成的代碼鎖定的是
this (實例事件)或聲明事件的類型(靜態(tài)事件)。而C# 4中,編譯器實現(xiàn)了線程安全,對原子
的訂閱和退訂使用了 Interlocked.CompareExchange<T> 。與之前對 lock 語句的修改不同,
面對舊版本的.NET Framework時,這項更改同樣適用。
其次,在聲明事件的類中,事件名稱的含義改變了。以前,在聲明事件的類中訂閱(或退訂)
事件——如 Click += DefaultClickHandler; ——將直接使用后臺字段,完全跳過 add/remove
實現(xiàn)。現(xiàn)在情況變了,使用 += 或 -= 時,事件的名稱就指向事件本身,而不再是后臺字段。當(dāng)名
稱用于其他意圖時(通常為分配或調(diào)用),則仍然指向后臺字段。
盡管在平時使用時你可能不會注意這兩處改變,不過它們是合理的,可以使一切變得整潔。
Chris Burrows在他的博客中深入研究了這個話題,想了解更多內(nèi)容可以參考http://mng.bz/Kyr4。
?
轉(zhuǎn)載于:https://www.cnblogs.com/kikyoqiang/p/10116459.html
總結(jié)
以上是生活随笔為你收集整理的13.4 对锁和字段风格的事件的微小改变的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 并发
- 下一篇: 化验室的废液处理装置怎么安装?