C#中的原子操作Interlocked,你真的了解吗?

本文探讨了C#中Interlocked.Exchange的使用,分析了在特定情况下可能导致的问题,涉及多线程同步和CPU核心间的缓存同步。通过案例和汇编代码解析,提出在某些场景下可能存在的时间窗口导致的判断错误,并提供了解决方案,包括添加volatile关键字或修改比较方式。文章还提及了相关资料和作者的思考。
摘要由CSDN通过智能技术生成

一、背景

  这个标题起的有点标题党的嫌疑[捂脸],这个事情的原委是这样的,有个Web API的站点在本地使用Release模式Run的时候出现问题,但是使用Debug模式则不会。通过打日志定位到问题在如下的这个代码这里:  

复制代码

        private static int _flag;

        public void ExactlyOnceMethod()
        {
            var original = Interlocked.Exchange(ref _flag, 1);
            if (original == _flag)
            {
                // 1.重复进入
            }
            else
            {
                // 2.第一次进入
            }
        }

复制代码

  理论上,会有一次请求进入到2中,但是实际问题是全部都进入到了1中。

二、代码描述

  这个代码很简单,就做了2个事情,1是使用Interlocked.Exchange将_flag变量进行赋值。2是将Interlocked.Exchange操作后返回的原始值与_flag变量进行对比,如果相等说明这个变量已经被修改过了,表示这里是重入了。如果不是则说明第一次进入此方法。

  关于Interlocked.Exchange的解释,见微软官网文档,传送门在此:https://msdn.microsoft.com/zh-cn/library/d3fxt78a.aspx 

 

三、越分析越黑暗

  好了,咋一看了好几分钟,也没看出有什么不妥的地方,那么首先就往多线程问题上考虑了。但是这里唯一的共享变量就是_flag,走的又是CAS操作,在这里不存在多线程问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值