开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 3231|回复: 1
收起左侧

[C#图文教程] C# 线程同步专题 - 第一篇 同步问题的产生

[复制链接]
发表于 2019-5-31 14:18:50 | 显示全部楼层 |阅读模式   广东省揭阳市
本帖最后由 老郭 于 2019-5-31 14:21 编辑

下面由一段代码来引申出如果没有线程同步带来的问题

static int sum = 0;
static void Main(string[] args)
{
    //尽可能大一些 , 触发竞争的几率就高 多运行几次查看结果
    Parallel.For(0, 100000, i => {
        sum++; 
    });
    Console.WriteLine(sum);
}

​        上面的代码很简单我们使用了并行库,在多线程并行执行的情况下对一个全局的静态变量进行递增操作,我们都知道在单核CPU架构上多线程的执行其实是时间片的切换,那么本质上只要 sum++ 这个语句是原子操作的话就不会有任何问题,因为在单核CPU架构上始终都只有一个线程在执行( 注:原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉)

​        那么 sum++ 是原子性的吗 , 从代码上看 sum++ 感觉就是原子性的 , 因为只有一句代码,代表着将 sum 所标识的内存中的值加1,然而在我们代码被编译之后我们看到从机器指令翻译的汇编代码中 sum++ 这种自增操作有会被翻译成如下常见的2种形式  (不同的编译器,不同的架构 如 x86 或 x64 , 或CPU架构都会导致编译/运行结果有差别)

第一种

mov eax,dword ptr ds:[0x13A440C] //从 sum 中取值 到 eax 寄存器中
inc eax //执行 +1 操作
mov ds:[0x13A440C],dword ptr eax //将自增后的值放回到 sum 变量中

​        上面的代码是c#代码被编译执行时转换成的汇编代码,可以看到 sum++ 这个操作在执行时被分成了三步,这里假设,我们的CPU是单核的 , 并且当前有2个线程同时运行这段代码 sum的初始值是0 ,线程1在运行完 inc eax 的时候 ,系统时钟引发了中断,导致线程2 开始执行, 我们来分析一下 线程1 在执行 +1 操作前首先从内存取出sum变量中存储的值,然后放到 eax 寄存器中 执行 +1 操作 ,当+1操作执行完成时 需要最后一步操作将增加的值放回到 sum变量中,这时却系统的时钟却刚好中断了导致线程2开始执行.

​        线程2的执行过程与线程1是一样,需要先获取值到寄存器执行 +1再放回到sum变量中,如果线程2执行完成了,此时内存中 sum 变量的值 应该是 1,而线程1在线程2执行完成后继续开始执行,此时只是执行第三句代码 也就是将 eax 的值 放回到 sum 中, 所以结果也是1

我们执行了2次sum++ , 本来sum的结果应该是 2 , 但因多线程竞争的问题导致了结果错误

第二种

inc dword ptr ds:[0x13A440C] 

大家可以在VS中下断点,然后转到汇编代码调试,会看到这个过程
1559272092943.png
1559272218269.png

​        第二种生成的汇编代码,可以保证再单核CPU多线程的情况下不出问题,因为尽管会有线程切换的发生,但是只会发生在一句代码的执行前或执行后,而不会在执行的过程中中断执行,所以从单核CPU的角度上面这个代码不会发生问题,但是在多核CPU中仍然会发生问题,因为上面这个代码是可以被多个线程同时执行的,因此仍然会产生数据错误的现象

​        那么当同步问题发生后我们应该如何处理这个问题,让我们在下篇文章中与大家详细说明,大家也可以关注我的C#专题课程,在视频课程中一起学习

评分

参与人数 1好评 +1 精币 +2 收起 理由
qingshanlushui + 1 + 2 新技能已get√

查看全部评分

发表于 2019-5-31 15:24:27 | 显示全部楼层   河南省周口市
高手,这是高手
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表