linux编程的108种奇易做图巧计-7(Lock-free实验)【答网友问】
接上次:html">/kf/201011/77843.html
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 不是原子操作的可运行的程序来证明,期待这两位网友和其他能作出这个实验的朋友们发给我,我贴出来,让大家一起学习一下,共同把这个问题深入搞清楚,如果不是常见的计算机或者操作系统也没关系,至少大家多长个见识。
补充:综合编程 , 其他综合 ,