GNU C中x++是原子操作吗?
答案 不是 。 x++由3条指令完成 。x++在单CPU下不是原子操作。对应3条汇编指令
movl x, %eax
addl $1, %eax
movl %eax, x
在vc2005下对应
++x;
004232FA mov eax,dword ptr [x]
004232FD add eax,1
00423300 mov dword ptr [x],eax
仍然是3条指令。
所以++x,x++等都不是原子操作。因其步骤包括了从内存中取x值放入寄存器,加寄存器,把值写入内存三个指令。
面试题:i初始值为0,i++在两个线程里边分别执行100次,能得到的最大值和最小值分别是多少?
得到最大值必然是200,一切有序进行。
最小值呢?
i++可以理解为三步,
r=x;
r=r+1;
x=r;
取值存入寄存器,寄存器自增,寄存器值赋给x(不同线程的寄存器是独立的)
我的理解:
假设当前有线程1和线程2,线程2先运行第一步,r2=0,x=0
线程1运行i++99次,r1=99,x=99
线程2运行第二步、第三步,r2=1,x=1
线程1运行第100次i++的第一步、第二步,r1=2,x=1
线程2运行完所有
线程1运行第100次i++的第三步,r1=2,x=2
网上的说法(也很好):
如此,假设两个线程的执行步骤如下:
1. 线程A执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU1的寄存器中值为1,内存中为0;
2. 线程B执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU2的寄存器中值为1,内存中为0;
3. 线程A继续执行完成第99次i++,并把值放回内存,此时CPU1中寄存器的值为99,内存中为99;
4. 线程B继续执行第一次i++,将其值放回内存,此时CPU2中的寄存器值为1,内存中为1;
5. 线程A执行第100次i++,将内存中的值取回CPU1的寄存器,并执行加1,此时CPU1的寄存器中的值为2,内存中为1;
6. 线程B执行完所有操作,并将其放回内存,此时CPU2的寄存器值为100,内存中为100;
7. 线程A执行100次操作的最后一部分,将CPU1中的寄存器值放回内存,内存中值为2;
8. 结束!
答案:最小值2,最大值200
参考文献
https://software.intel.com/zh-cn/blogs/2010/01/14/cpucpu
http://blog.csdn.net/zmldlut/article/details/8219867