原子操作与并发安全

一直以来,都对原子操作和并发安全都有些误解,认为一个操作不是原子的,那它就不是并发安全的,这样以来,就迟疑了,这么说来:
C语言一个简单的赋值语句也不是原子的咯? a = b是否是原子操作? 见代码如下:

int main() {
int a = 0;
int b = 2;
a = b;
}


编译这段代码: g++ -c -g -Wa,-adlhn Assign.c > Assign.asm
可以发现(只显示a = b部分asm码):

movl -8(%ebp), %eax
movl %eax, -4(%ebp)

大家看,它由两条汇编指令完成操作,简单解释一下:
[list]
[*]a ==> -4(%ebp)
[*]b ==> -8(%ebp)
[*]movl与mov参数顺序相反,movl SRC, DEST
[*]movl -8(%ebp), %eax ==> movl b, %eax (先将寄存器%eax赋值为b的值)
[*]movl %eax, -4(%ebp) ==> movl %eax, a (将a的值赋值为寄存器%eax的值)
[/list]
经过这两个指令,最终实现了a = b的赋值

[b]所以,似乎我可以负责任的说,a = b不是原子的。[/b]

好吧,既然它不是原子的,那它又是否是并发安全的呢?当然,上面这个例子似乎与并发没多大关系,那就定义这样一个类吧:

class CObject {
private:
int _v;
public:
CObject() { _v = 0; }
void putValue(int v) { _v = v; }
int getValue() const { return _v; }
};

同样是只看_v = v部分的汇编指令

movl 8(%ebp), %eax
movl 12(%ebp), %edx
movl %edx, (%eax)

解释如下:
[list]
[*] 8(%ebp) ==> _v
[*] 12(%ebp) ==> v
[*] movl 8(%ebp), %eax ==> %eax赋值为_v的地址
[*] movl 12(%ebp), %edx ==> %edx赋值为v的地址
[*] movl %edx, (%eax) ==> %eax对应地址的值赋值为%edx对应的值
[/list]
[b]过程其实都一样,无非为了说明,赋值操作不是原子的。[/b]

如果是我以前的理解,不是原子操作就不是并发安全的,那并发程序该怎么写阿?

[color=red][b]其实只能说,这是我的误解,首先我们要仔细想想,在什么情况下才会产生并发问题:
就我的理解,多个线程竞争共享数据时,才会有并发问题,回过头再来看上面那几行汇编代码,_v属于共享数据,可真正产生竞争只可能在movl %edx, (%eax),这个时候,可能有多个线程想进行这一步操作,事实上这个操作应该算是原子的吧,因此这样的赋值操作就应该是并发安全的。[/b][/color]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值