网站建设要学会什么,wordpress头像怎么修改,外墙清洗,山东省住房和城乡建设厅政务服务【导读】私下空余时间一直在研究开源框架#xff0c;当然也就少不了学习优秀源码#xff0c;本文也是我查看有关源码时#xff0c;触碰到我个人知识盲区#xff0c;做此记录#xff0c;分享下Interlocked.CompareExchange这玩意用法被讲的很烂了#xff0c;为何再次被提及… 【导读】私下空余时间一直在研究开源框架当然也就少不了学习优秀源码本文也是我查看有关源码时触碰到我个人知识盲区做此记录分享下Interlocked.CompareExchange这玩意用法被讲的很烂了为何再次被提及主要看了下官网对其使用描述可能对于部分童鞋来讲具备一定迷惑性需我们进一步消化下话不多讲我们来看看吧~~~浅谈如标题关于啥时候用此语法这.....此处省略若干字上代码var location  1;var value  3;var compared  1;Interlocked.CompareExchange(ref location, value, compared);
若原始值location与比较值compared一致则将当前值value替换原始值。如图上述此时原始值将为3毫无疑问我们很清楚这是基本用法问题来了该语法既可比较基本类型也可比较引用类型当比较对象时官方还特此备注注意比较对象的引用相等性而不是值相等性。结果两个具有相同值类型例如整数3的装箱实例始终看起来不相等并且不执行任何操作。不要将此重载用于值类型。初次看稍不注意的迷惑性来了解释如下截图从描述上看一部分童鞋是不是会认为原始值为空则会引发空引用异常如下代码object o1  null;object o2  null;Interlocked.CompareExchange(ref o1, o2, null);
运行上述代码将不会抛出空引用异常这是为何难道官方解释有误接下来我们深入探讨下深谈如标题若对C语言有所了解则不会存在疑惑官方解释为空指针不是空而我们代码是空引用二者不可同日而语C#中对于引用类型定义现有的变量必将存在引用所以在C#中不可能存在空引用所以我们是不是可以认为必然不会存在抛出空引用异常官方解释为空指针和null其实并不是同一个概念如此一解释极易引起概念混淆还不如去掉显得有点多余再想想也不是那么绝对个人以为至少在托管情况下理论上应该不会抛出任何异常非托管情况下可能没有保证或者通过IL操作底层也会触发上述空引用异常综上个人理解官方解释谈不上迷惑性只是好像有点会引起概念混淆让部分童鞋以为不能传递空希望没将各位绕晕那么我们在哪些场景下会用到上述原始值为空的情况呢比如确保对象初始化如下public class Order
{public Address Address{get{return CreateAddress();}}private Address CreateAddress()  new Address();
}public class Address
{
}
当我们在Order内部使用Address时确保其实例已完全初始化如下static Address EnsureAddressInitialized()
{var order  new Order();FuncOrder, 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语法表明对象实例绝不可能为空该语法有返回值那打印结果是否和替换后的原始值一样呢不是除了替换原始值外针对所有情况返回值都是最初原始值即旧值。据我所知该语法底层直接操作CPU处理器指令当然也是原子性操作即便是操作系统也无法执行中断操作线程可以在指令执行之前被抢占但在指令执行期间不会被抢占换言之绝不会出现当原始值和比较值比较相等时而另一线程指令更改原始值的情况基于上述理论所以才有了网上大多数通过循环方式对其返回结果赋最新原始值实现并发无锁修改操作public static Address EnsureAddressInitialized(ref Address target,Order order, FuncOrder, Address func){if (target ! null){return target;}while (Interlocked.CompareExchange(ref target, func(order), null)  null){break;}return target;}为避免上述没必要的循环操作同时也为避开CPU缓存我们进一步进行代码优化通过使用Volatile关键字获取内存最新存储数据最终演变成如下这般public static Address EnsureAddressInitialized(ref Address target,Order order, FuncOrder, Address func)
{var tmp  Volatile.Read(ref target);if (tmp ! null){return tmp;}Interlocked.CompareExchange(ref target, func(order), null);return target!;
}???? 概念的混淆可能会存在使用上的疑惑同时我们基于理论逐步优化实现并发无锁修改操作