您的位置:首页 > 编程语言 > C语言/C++

C语言的赋值++是否为原子操作

2013-11-03 22:14 609 查看
相关概念:

时钟周期、总线周期和指令周期

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:

[cpp]
view plaincopy

#include <stdio.h>

void fun1()
{
volatile int m;
volatile int n;
m = 99;
n = m;
}

void fun2()
{
volatile int n = 10;
n++;
}

int main(int argc, char** argv)
{
fun();

return 0;
}

汇编:

gcc -S main.c

查看fun1相关的指令:

[plain]
view plaincopy

pushq %rbp
movq %rsp, %rbp
movl $99, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, -8(%rbp)
leave

fun2相关指令:

[plain]
view plaincopy

pushq %rbp
movq %rsp, %rbp
movl $10, -4(%rbp)
leaq -4(%rbp), %rax
incl (%rax)
movl %eax, -4(%rbp)
leave

可以看到,n = m为两条指令:

movl -4(%rbp), %eax

movl %eax, -8(%rbp)

n++三条指令:

leaq -4(%rbp), %rax

incl (%rax)

movl %eax, -4(%rbp)

都是多条指令,所以,不是原子操作。

总结:

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

但是在操作系统中还是会介绍有这个概念的讲解,到时候留心分析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: