c++ 原子操作 赋值_C++ 随手笔记 原子操作

本文介绍了C++中的原子操作,通过示例展示了如何使用std::atomic避免数据竞争问题。原子操作使得变量的更新过程成为不可分割的单位,确保了多线程环境中的数据一致性。
摘要由CSDN通过智能技术生成

原子操作 在古代希腊时期,亚里士多德就曾经发想,如果物体不断分割下去,是否会有无法再继续切割的情况?因此亚里士多德假想的一种粒子,它无法继续切割,这个假想粒子称为原子。由于原子无法分割的特性,所以它只...

原子操作

在古代希腊时期,亚里士多德就曾经发想,如果物体不断分割下去,是否会有无法再继续切割的情况?因此亚里士多德假想的一种粒子,它无法继续切割,这个假想粒子称为原子。由于原子无法分割的特性,所以它只有 "存在" 和 "虚无" 两种状态,这是非常简单与优美的思想,我们希望这种简洁的想法也能在程式语言上表现出来,希望运算只有"完成" 和 "没完成" 两种状态,这种想法称为原子操作。

原子操作的优势

在现代的电脑中,我们对一个整数做加法,如

int a++;

这个加法不是一步完成的,所以在加法的过程中会有一个中间态,假设此时有另一个执行绪读取它,就会有 data race 问题。但如果用一些方法使它变成原子性的,让它只有 "完成" 和 "没完成" ,就可以保证当另一个执行绪读取它时有正确性。

範例

在 C++11 时引入原子操作的类别

#include // atomic

std::atomic a; // 类型为 float

std::atomic b; // 类型为 int

std::atomic<:uint64_t> c; // 类型为 std::uint64_t

没有原子操作

#include

#include

#include

static int cnt = 0;

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

std::vector<:thread> threads;

threads.emplace_back([&](){

for (int i = 0; i < 10000000; ++i) {

cnt++;

}

});

threads.emplace_back([&](){

for (int i = 0; i < 10000000; ++i) {

cnt++;

}

});

for (auto &t : threads) {

t.join();

}

std::cout << " count : " << cnt << std::endl;

return 0;

}

有原子操作

#include

#include

#include

#include

static std::atomic cnt{0};

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

std::vector<:thread> threads;

threads.emplace_back([&](){

for (int i = 0; i < 10000000; ++i) {

cnt++;

}

});

threads.emplace_back([&](){

for (int i = 0; i < 10000000; ++i) {

cnt++;

}

});

for (auto &t : threads) {

t.join();

}

std::cout << " count : " << cnt << std::endl;

return 0;

}

实际运行后可以发现 cnt 不一样。

后记

原子操作有两个常用的函式

std::atomic a;

a.store(100); // 储存 100 到 a

auto b = a.load() // 拿出 a 储存的数字

当然还有一系列强大的函式,透过设计,可以用来取代 mutex,这有机会以后再介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值