【导读】私下空余时间一直在研究开源框架,当然也就少不了学习优秀源码,本文也是我查看有关源码时,触碰到我个人知识盲区,做此记录,分享下

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();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语法表明对象实例绝不可能为空

该语法有返回值,那打印结果是否和替换后的原始值一样呢?不是,除了替换原始值外,针对所有情况,返回值都是最初原始值即旧值。

据我所知,该语法底层直接操作CPU处理器指令,当然也是原子性操作,即便是操作系统也无法执行中断操作,线程可以在指令执行之前被抢占,但在指令执行期间不会被抢占,换言之,绝不会出现,当原始值和比较值比较相等时,而另一线程指令更改原始值的情况

基于上述理论,所以才有了网上大多数通过循环方式对其返回结果赋最新原始值实现并发无锁修改操作

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;}

为避免上述没必要的循环操作,同时也为避开CPU缓存,我们进一步进行代码优化,通过使用Volatile关键字获取内存最新存储数据,最终演变成如下这般

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!;
}

???? 概念的混淆可能会存在使用上的疑惑,同时我们基于理论逐步优化,实现并发无锁修改操作

聊聊Interlocked.CompareExchange吧?相关推荐

  1. Interlocked.CompareExchange

    class SourceManager { private SourceManager() { } private static SourceManager sourceManager; public ...

  2. C# Interlocked 笔记

    无锁代码下,在读写字段时使用内存屏障往往是不够的.在 64 位字段上进行加.减操作需要使用Interlocked工具类这样更加重型的方式.Interlocked也提供了Exchange和Compare ...

  3. C#多线程编程(6)--线程安全2 互锁构造Interlocked

    在线程安全1中,我介绍了线程同步的意义和一种实现线程同步的方法:volatile.volatile关键字属于原子操作的一种,若对一个关键字使用volatile,很多时候会显得很"浪费&quo ...

  4. C#【Thread】Interlocked 轻量级锁

    什么说它是轻量级呢?因为它仅对整形数据(即int类型,long也行)进行同步. 具体使用如下表: Interlocked.Increment(ref value) 数值加一(原子性操作) Interl ...

  5. C# Interlocked类的事例

    static void Main(string[] args)         {             int a = 20;             int b = 20;            ...

  6. 把三千行代码重构为15行

    2019独角兽企业重金招聘Python工程师标准>>> 如果你认为这是一个标题党,那么我真诚的恳请你耐心的把文章的第一部分读完,然后再下结论.如果你认为能够戳中您的G点,那么请随手点 ...

  7. C#线程同步的几种方法

    在网上也看过一些关于线程同步的文章,其实线程同步有好几种方法,下面我就简单的做一下归纳. 一.volatile关键字 volatile是最简单的一种同步方法,当然简单是要付出代价的.它只能在变量一级做 ...

  8. C# 语言规范_版本5.0 (第10章 类)

    1. 类 类是一种数据结构,它可以包含数据成员(常量和字段).函数成员(方法.属性.事件.索引器.运算符.实例构造函数.静态构造函数和析构函数)以及嵌套类型.类类型支持继承,继承是一种机制,它使派生类 ...

  9. 【转】[C# 基础知识系列]专题四:事件揭秘

    引言: 前面几个专题对委托进行了详细的介绍的,然后我们在编写代码过程中经常会听到"事件"这个概念的,尤其是写UI的时候,当我们点击一个按钮后VS就会自动帮我们生成一些后台的代码,然 ...

最新文章

  1. 为什么ConcurrentHashMap的读操作不需要加锁?
  2. php 中continue break exit return 的区别
  3. PHP中 的全局变量$_SERVER
  4. 如何让history命令显示带时间
  5. ICMP 隧道——将流量封装进 IMCP 的 ping 数据包中,旨在利用 ping 穿透防火墙的检测...
  6. 计算两个数的乘积java编写_Java模拟计算机的整数乘积计算功能示例
  7. C#算法设计查找篇之03-插值查找
  8. Docker下ETCD集群搭建
  9. HDU 5978 2016ICPC大连 H: To begin or not to begin
  10. python—如何处理文件中的缺失值
  11. Security+ 学习笔记10 软件质量保证
  12. 【虚拟机】VMware启动时报错:该虚拟机似乎正在使用中....请按“获取所有权(T)”按钮获取它的所有权
  13. 3Q双向可控硅与4Q双向可控硅对比好处
  14. 解析美团联盟,美团分销联盟,美团福利宝,外卖美天赚区别和玩法
  15. 计算机专业拜年语,适合拜年发的朋友圈祝福语:过年拜年的说说
  16. 条码生成器如何导入CSV文件批量生成条形码
  17. 洛谷P5520 [yLOI2019] 青原樱 题解
  18. 如何提升流量的转化率
  19. CSDN 空间:“迷你博客”很迷人(2)收藏
  20. (转载)BOX2D V2.3.0 用户手册中文版(第8章)-关节

热门文章

  1. Factory Method工厂方法
  2. [Codeforces700E Cool Slogans]
  3. Django模板语言中的自定义方法filter过滤器实现web网页的瀑布流
  4. Couchbase概述
  5. android获取手机机型、厂商、deviceID基本信息
  6. redis学习之三配置文件redis.conf 的含义
  7. Kinect开发笔记之八C#实现Kinect声音的追踪
  8. Teams App 扫描二维码
  9. Python_list部分功能介绍
  10. centOS下安装jdk1.8