日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

聊聊Interlocked.CompareExchange吧?

發(fā)布時間:2023/12/4 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 聊聊Interlocked.CompareExchange吧? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
【導(dǎo)讀】私下空余時間一直在研究開源框架,當然也就少不了學(xué)習(xí)優(yōu)秀源碼,本文也是我查看有關(guān)源碼時,觸碰到我個人知識盲區(qū),做此記錄,分享下

Interlocked.CompareExchange這玩意用法被講的很爛了,為何再次被提及,主要看了下官網(wǎng)對其使用描述可能對于部分童鞋來講具備一定迷惑性,需我們進一步消化下,話不多講,我們來看看吧~~~

淺談如標題

關(guān)于啥時候用此語法,這.....此處省略若干字,上代碼

var?location?=?1;var?value?=?3;var?compared?=?1;Interlocked.CompareExchange(ref?location,?value,?compared);

若原始值(location)與比較值(compared)一致,則將當前值(value)替換原始值。如圖上述,此時原始值將為3,毫無疑問,我們很清楚這是基本用法

問題來了,該語法既可比較基本類型也可比較引用類型

當比較對象時,官方還特此備注注意:

比較對象的引用相等性,而不是值相等性。結(jié)果,兩個具有相同值類型(例如,整數(shù)3)的裝箱實例始終看起來不相等,并且不執(zhí)行任何操作。不要將此重載用于值類型。


初次看,稍不注意的迷惑性來了,解釋如下截圖

從描述上看,一部分童鞋是不是會認為,原始值為空,則會引發(fā)空引用異常,如下代碼

object?o1?=?null;object?o2?=?null;Interlocked.CompareExchange(ref?o1,?o2,?null);

運行上述代碼將不會拋出空引用異常,這是為何?難道官方解釋有誤,接下來我們深入探討下

深談如標題

若對C語言有所了解,則不會存在疑惑,官方解釋為空指針(不是空),而我們代碼是空引用,二者不可同日而語

C#中對于引用類型,定義現(xiàn)有的變量必將存在引用,所以在C#中不可能存在空引用,所以我們是不是可以認為必然不會存在拋出空引用異常

官方解釋為空指針和null其實并不是同一個概念,如此一解釋,極易引起概念混淆,還不如去掉,顯得有點多余

再想想,也不是那么絕對,個人以為,至少在托管情況下理論上應(yīng)該不會拋出任何異常,非托管情況下可能沒有保證,或者通過IL操作底層,也會觸發(fā)上述空引用異常

綜上個人理解,官方解釋談不上迷惑性,只是好像有點會引起概念混淆,讓部分童鞋以為不能傳遞空,希望沒將各位繞暈

那么我們在哪些場景下會用到上述原始值為空的情況呢?比如確保對象初始化,如下:

public?class?Order {public?Address?Address{get{return?CreateAddress();}}private?Address?CreateAddress()?=>?new?Address(); }public?class?Address { }

當我們在Order內(nèi)部使用Address時,確保其實例已完全初始化,如下:

static?Address?EnsureAddressInitialized() {var?order?=?new?Order();Func<Order,?Address>?func?=?f?=>?f.Address;Address?target?=?null;var?result?=?Interlocked.CompareExchange(ref?target,?func(order),?null);Console.WriteLine(result?==?null);Console.WriteLine(target);return?target!; }

上述方法返回對象實例時,我們使用C# 8.0語法表明對象實例絕不可能為空

該語法有返回值,那打印結(jié)果是否和替換后的原始值一樣呢?不是,除了替換原始值外,針對所有情況,返回值都是最初原始值即舊值。

據(jù)我所知,該語法底層直接操作CPU處理器指令,當然也是原子性操作,即便是操作系統(tǒng)也無法執(zhí)行中斷操作,線程可以在指令執(zhí)行之前被搶占,但在指令執(zhí)行期間不會被搶占,換言之,絕不會出現(xiàn),當原始值和比較值比較相等時,而另一線程指令更改原始值的情況

基于上述理論,所以才有了網(wǎng)上大多數(shù)通過循環(huán)方式對其返回結(jié)果賦最新原始值實現(xiàn)并發(fā)無鎖修改操作

public?static?Address?EnsureAddressInitialized(ref?Address?target,Order?order,?Func<Order,?Address>?func){if?(target?!=?null){return?target;}while?(Interlocked.CompareExchange(ref?target,?func(order),?null)?==?null){break;}return?target;}

為避免上述沒必要的循環(huán)操作,同時也為避開CPU緩存,我們進一步進行代碼優(yōu)化,通過使用Volatile關(guān)鍵字獲取內(nèi)存最新存儲數(shù)據(jù),最終演變成如下這般

public?static?Address?EnsureAddressInitialized(ref?Address?target,Order?order,?Func<Order,?Address>?func) {var?tmp?=?Volatile.Read(ref?target);if?(tmp?!=?null){return?tmp;}Interlocked.CompareExchange(ref?target,?func(order),?null);return?target!; }

?????概念的混淆可能會存在使用上的疑惑,同時我們基于理論逐步優(yōu)化,實現(xiàn)并發(fā)無鎖修改操作

總結(jié)

以上是生活随笔為你收集整理的聊聊Interlocked.CompareExchange吧?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。