找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6058|回复: 2

[原]C语言赋值语句是不是原子操作?

[复制链接]
发表于 2012-4-16 23:32:04 | 显示全部楼层 |阅读模式
经常看到有同学讨论,C语言的赋值语句是不是原子操作?C语言的++语句是不是原子操作?

webopedia
Atomic implies indivisibility and irreducibility, so an atomic operation must be performed entirely or not performed at all.
An operation during which a processor can simultaneously read a location and write it in the same bus operation. This prevents any other processor or I/O device from writing or reading memory until the operation is complete.


osdev:
An atomic operation is an operation that will always be executed without any other process being able to read or change state that is read or changed during the operation. It is effectively executed as a single step, and is an important quality in a number of algorithms that deal with multiple indepent processes, both in synchronization and algorithms that update shared data without requiring synchronization.

相关概念:

时钟周期、总线周期和指令周期
1.时钟周期:微处理器执行指令的最小时间单位,又称T状态。它通常与微机的主频有关。
2.总线周期:CPU对存储器或I/O端口完成一次读/写操作所需的时间。如8086微处理器的基本总线周期由四个时钟周期T1~T4组成,80486微处理器的基本总线周期由T1和T2两个时钟周期组成。当外设速度较慢时,可插入等待周期Tw。
3.指令周期:CPU执行一条指令所需要的时间。指令周期由若干个总线周期组成,不同指令执行的时间不同。同一功能的指令,在寻址方式不同时,所需要的时间也不同。

总线操作周期:微机系统各部件之间的信息交换是通过总线操作周期完成的,一个总线周期通常分为以下四个阶段。
1.总线请求和仲裁阶段:当有多个模块提出总线请求时,必须由仲裁机构仲裁,确定将总线的使用权分配给哪个模块。
2.寻址阶段:取得总线使用权的模块,经总线发出本次要访问的存储器或I/O端口的地址和有关命令。
3.传送数据阶段:主模块(指取得总线控制权的模块)与其他模块之间进行数据的传送。
4.结束阶段:主模块将有关信息从总线上撤除,主模块交出对总线的控制权。

CPU最小的执行单元是指令,一个指令周期可能包括多个总线周期。
我们可以得到:
1. 在单处理器下,一个操作只包括一个cpu指令可以保证是原子操作。如果一个操作包含多个cpu指令不是原子操作。
2. 在多处理器下,由于一个cpu指令周期可能包含多个总线周期,就有可能出现其他处理器在一个指令执行期间访问了其相关的状态。因此,多处理器下,指令执行期间还必须锁总线,才能保证CPU指令的原子性


我们看下C语言的赋值和++操作
代码main.c:
  1. #include <stdio.h>
  2. void fun1()
  3. {
  4.         volatile int m;
  5.         volatile int n;
  6.         m = 99;
  7.         n = m;
  8. }
  9. void fun2()
  10. {
  11.         volatile int n = 10;
  12.         n++;
  13. }
  14. int main(int argc, char** argv)
  15. {
  16.         fun();
  17.         return 0;
  18. }
复制代码
汇编:
gcc -S main.c
查看fun1相关的指令:
  1.         pushq   %rbp
  2.         movq    %rsp, %rbp
  3.         movl    $99, -4(%rbp)
  4.         movl    -4(%rbp), %eax
  5.         movl    %eax, -8(%rbp)
  6.         leave
复制代码
fun2相关指令:
  1.         pushq   %rbp
  2.         movq    %rsp, %rbp
  3.         movl    $10, -4(%rbp)
  4.         leaq    -4(%rbp), %rax
  5.         incl    (%rax)
  6.         movl    %eax, -4(%rbp)
  7.         leave
复制代码

可以看到,n = m为两条指令:
  1. movl    -4(%rbp),
  2. %eax
  3.         movl    %eax, -8(%rbp)
复制代码
n++三条指令:
  1. leaq   
  2. -4(%rbp), %rax
  3.          incl    (%rax)   
  4.          movl    %eax,
  5. -4(%rbp)
复制代码
都是多条指令,所以,不是原子操作。

总结:
原子操作和硬件实现、编译器实现都紧密相关,因此,单纯的在高级语言的层次讨论原子操作,没有太大的意义。

参考:
http://wiki.osdev.org/Atomic_operation
http://www.webopedia.com/TERM/A/atomic_operation.html
http://www.chinaunix.net/jh/23/804826.html
http://odetocode.com/blogs/scott/archive/2006/05/17/atomic-operations.aspx

作者:yfkiss 发表于2012-4-13 10:34:04 原文链接

发表于 2012-4-27 17:34:55 | 显示全部楼层
嗯,还真的学习了,看来学好底层的东西很重要………………
发表于 2012-5-4 10:17:16 | 显示全部楼层
这东西不但困惑新手还困惑一些老程序员。以后谁再跟我争论这个问题我就给他看这个文章:lol
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 17:19 , Processed in 0.016889 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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