linux编程的108种奇淫巧计-7(Lock-free实验)【答网友问】

本文针对网友关于`size_t u=g_uCount`是否需要原子操作的问题进行解答,探讨了volatile关键字在多核环境中的作用,以及在SMP架构下内存访问的原子性。即便不使用volatile,实验结果依然正确,但原因未能完全解释。通过银行服务的比喻,说明了多线程在处理慢速任务时可提升吞吐率。作者期待更多实验案例以深入理解问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       接上次博客:http://blog.youkuaiyun.com/pennyliang/archive/2010/11/07/5993138.aspx

 

gangban_lau 发表于Tue Nov 09 2010 19:07:08 GMT+0800 (China Standard Time)   举报 回复 删除

回复 pennyliang: 我的意思 是 size_t u = g_uCount 这个赋值操作本身可能出现问题。只有这个操作是原子的,才能确保取到当前值。按照 libc 说明,int access 可以看成原子的。不过改成 libc 的 sig_atomic_t 应该更说明问题,否则后续的 CAS 实际是没有意思的。
li258227345 发表于Wed Nov 10 2010 11:41:38 GMT+0800 (China Standard Time)   举报 回复 删除

回复 gangban_lau:楼上的说得对,这里有问题哦.经不起推敲

 

      网友回复关于size_t u=g_uCount这个必须是原子操作才可以保证正确性,这里做一个答复。

 

     首先注意我对g_uCount的变量定义加了volatile,告诉编译器不要将这个变量优化进寄存器,也就是在多核情况下,每个核上的线程在从g_uCount取值时都是从内存中取的,也就是会锁总线,这显然是一个原子操作。在扯远一点从内存地址取值怎么就相当于锁总线呢?因为我们目前都是SMP架构,多个核共享一个内存,对称多处理的架构,核多个,L1Cache多个,但内存是一个,在同一时刻只有一个核可以从内存中取出来数据。

     如果大家觉得不是原子操作,经不起推敲,可以举个例子来说服我,只一句经不起推敲是否不太妥当?

 

     其次,即便把volatile修饰去掉,结果也是正确的,这个确实很难解释,我目前的水平还达不到完全解释的能力,有兴趣的读者可以参见:http://www.newsmth.net/bbstcon.php?board=CSArch&gid=34641。我想做芯片或者做编译器的同学应该能知道原因。

 

       最后,这里举得例子都是很简单的,比如我的试验机只有4个核,在这个例子中,4个线程是最好的,多了反而无益,但实践中,是很难避免有慢速的设备和慢速的操作,超过4个线程通常都是有益的,可以在分时操作系统时间片的作用下,获得更好的吞吐率。

 

      我们可以举个例子,比如银行有4个服务员(看成4core Cpu),有一票人(看做多个线程)在请求服务,现在的策略是分时服务,在某个老人(看做是一个线程)在窗口办一张银行卡,需要填表,该服务员每一个周期回头来检查一下老人是否填好了,没填好就处理别人的请求。这样总的吞吐率比服务员死等老人填完表要好得多。

 

      最后我还是特别期待看到在g_uCount被修饰为volatile,且size_t u=g_uCount 不是原子操作的可运行的程序来证明,期待这两位网友和其他能作出这个实验的朋友们发给我,我贴出来,让大家一起学习一下,共同把这个问题深入搞清楚,如果不是常见的计算机或者操作系统也没关系,至少大家多长个见识。

 

 

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值