前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >++i 是原子操作吗?

++i 是原子操作吗?

原创
作者头像
祥祥
修改2021-01-18 14:37:56
3.2K0
修改2021-01-18 14:37:56
举报
文章被收录于专栏:大写的CPP大写的CPP

答案:不是。

先看个例子:

代码语言:c++
复制
#include <iostream>
#include <atomic>
#include <thread>

using namespace std;

static atomic<int> atomicvalue(0);
static int value = 0;

constexpr int count = 10000;

void increase() {
    for (auto i = 0; i < count; i ++) {
        ++atomicvalue;
        ++value;
    }
}

void decrease() {
    for (auto i = 0; i < count; i ++) {
        --atomicvalue;
        --value;
    }
}

int main() {
    thread incr(increase);
    thread decr(decrease);

    incr.join();
    decr.join();

    // when thread all done
    // atomic value will be zero
    // non-atomic value may not be zero
    cout << "atomic value:" << atomicvalue << endl;
    cout << "non-atomic value:" << value << endl;

    return 0;
}

atomic value 一定是 0,但 non-atomic 的结果是看 cpu 心情的:

代码语言:javascript
复制
atomic value:0
non-atomic value:269
代码语言:javascript
复制
atomic value:0
non-atomic value:-2027

我们知道 i++ 是:先复制,再自增,再返回复制结果;++i 是只自增。但这些都是在 c++ 层面的逻辑。

我们把一段简单的代码汇编以下看看结果:

代码语言:javascript
复制
int main() {
    int i = 1;
    ++i;
    return 0;
}

汇编结果:

代码语言:javascript
复制
	.file	"mm.cpp"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$1, -4(%rbp)
	addl	$1, -4(%rbp)
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits

这三行是 ++i 的汇编结果:

代码语言:javascript
复制
movl	$1, -4(%rbp)
addl	$1, -4(%rbp)
movl	$0, %eax

所以 ++i 不是原子操作,非线程安全。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档