本文共 1042 字,大约阅读时间需要 3 分钟。
接上篇( ),对一个变量进行加法操作,可以是3条指令,也可以是1条指令。区别在于,1条指令属于原子操作,不会被打断,那是不是只要1条指令的形式,多线程之间就不需要加锁了呢?我们先试试看。(以下代码仅适用于x86平台,gcc编译器)
#include#include int count = 0;void *add(void *arg){ int i; for (i = 0; i< 10000; i++) { asm( "addl $1, %0 \n" : : "m"(count) : ); }}int main(int argc, char *argv[]){ pthread_t t1, t2; pthread_create(&t1, NULL, add, NULL); pthread_create(&t2, NULL, add, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf("%d\n", count); return 0;}
然后运行:
这是在一个多核处理器且支持对称多处理的系统上运行的结果。可见很大概率上,仍然存在同步问题。那为什么某些情况又能得到20000这个正确结果呢?鬼才知道,只能靠瞎猜。
多核多线程情况下,即便修改操作是单条指令,由于存在并发运行,也不能保证其原子性。幸好有taskset这个程序,可以设置cpu亲和性,我们先将其设置到单核试试看。
嗯貌似完美。
那如果亲和性设置成两个核心呢?
果然,有一定概率出现同步问题。
好了,文章要结束了,总得回到标题,类似电影要到时间了,反派再强大,也得找个方式被灭掉。lock前缀的意义在于,在多核且支持对称多处理的系统上,对于接下来的那条指令,能够保证其原子性。注意lock并不是能够往各个指令面前加的。至于如何保证了原子性,鬼才知道。
我们把add函数改写下:
for (i = 0; i< 10000; i++) { asm( "lock \n" "addl $1, %0 \n" : : "m"(count) : ); }
再运行几遍:
好了,像是那么回事了。
转载地址:http://quxyx.baihongyu.com/