C++11并发编程:原子操作atomic
一:概述
项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式。
为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一个线程执行过程中可能被内核临时挂起,这就是线程切换,当内核再次切换到该线程时,之前的数据可能已被修改,不能保证原子操作。
C++11提供了个原子的类和方法atomic,保证了多线程对变量原子性操作,相比加锁机制mutex.locak(),mutex.unlocak(),性能有几倍的提升。
所需头文件<atomic>
二:错误代码
//全局变量
int g_num = ; void fun()
{
for (int i = ; i < ; i++)
{
g_num++;
}
return ;
} int main()
{
//创建线程1
thread t1(fun);
//创建线程2
thread t2(fun);
t1.join();
t2.join(); cout << g_num << endl;
getchar();
return ;
}
应该输出结果20000000,实际每次结果都不一样,总是小于该值,正是由于多线程操作同一变量而没有保证原子性导致的。
三:加锁代码
//全局变量
int g_num = ;
mutex m_mutex; void fun()
{
for (int i = ; i < ; i++)
{
m_mutex.lock();
g_num++;
m_mutex.unlock();
}
return ;
} int main()
{
//获取当前毫秒时间戳
typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time1 = tp1.time_since_epoch().count(); //创建线程
thread t1(fun);
thread t2(fun);
t1.join();
t2.join(); cout << "总数:" << g_num << endl; //获取当前毫秒时间戳
microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time2 = tp2.time_since_epoch().count();
cout << "耗时:" << time2 - time1 << "ms" << endl; getchar();
return ;
}
执行结果:多次测试输出均为20000000,耗时在3.8s左右

四:atomic原子操作代码
//全局变量
atomic<int> g_num = ; void fun()
{
for (int i = ; i < ; i++)
{
g_num++;
}
return ;
} int main()
{
//获取当前毫秒时间戳
typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
microClock_type tp1 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time1 = tp1.time_since_epoch().count(); //创建线程
thread t1(fun);
thread t2(fun);
t1.join();
t2.join(); cout << "总数:" << g_num << endl; //获取当前毫秒时间戳
microClock_type tp2 = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
long long time2 = tp2.time_since_epoch().count();
cout << "耗时:" << time2 - time1 << "ms" << endl; getchar();
return ;
}
执行结果:多次测试输出均为20000000,耗时在1.3s左右

五:总结
c++11的原子类atomic相比使用加锁机制性能有2~3倍提升,对于共享变量能用原子类型的就不要再用加锁机制了。

扫码关注公众号
专注分享Java,C/C++,STL,Spring框架,mybatis框架,mysql,redis,分布式,高并发,设计模式,爬虫,docker,shell编程等相关技术,在这里一起探讨,一起学习,一起进步,不定期分享视频书籍资源,充分利用碎片化时间,让我们的技术之路更加有乐趣。
C++11并发编程:原子操作atomic的更多相关文章
- C++11 并发指南六(atomic 类型详解四 C 风格原子操作介绍)
前面三篇文章<C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)>.<C++11 并发指南六( <atomic> 类型详解二 std::at ...
- C++11 并发编程库
C++11 并发编程 C++11 新标准中引入了几个头文件来支持多线程编程,他们分别是: <atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_f ...
- C++11 并发指南六(atomic 类型详解三 std::atomic (续))
C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...
- C++11 并发指南六( <atomic> 类型详解二 std::atomic )
C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍) 一文介绍了 C++11 中最简单的原子类型 std::atomic_flag,但是 std::atomic_flag ...
- C++11 并发编程基础(一):并发、并行与C++多线程
正文 C++11标准在标准库中为多线程提供了组件,这意味着使用C++编写与平台无关的多线程程序成为可能,而C++程序的可移植性也得到了有力的保证.另外,并发编程可提高应用的性能,这对对性能锱铢必较的C ...
- C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)
C++11 并发指南已经写了 5 章,前五章重点介绍了多线程编程方面的内容,但大部分内容只涉及多线程.互斥量.条件变量和异步编程相关的 API,C++11 程序员完全可以不必知道这些 API 在底层是 ...
- C++11并发编程:多线程std::thread
一:概述 C++11引入了thread类,大大降低了多线程使用的复杂度,原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改.现在在C++11中只需使用语 ...
- C++11并发编程个人小结
thread_local变量在每个线程第一次执行到时初始化(类似static),并在每个线程各自累加,并在线程结束时释放. std::condition_variable:: wait(std::un ...
- C++11并发编程:async,future,packaged_task,promise
一:async std::async:用于创建异步任务,可以代替创建线程,函数原型:async(std::launch::async | std::launch::deferred, f, args. ...
随机推荐
- C# 判断一个数是不是奇数/偶数
一般普通版: private bool IsOdd(int num) { ) == ; } 通过判断取余 现在升级版: private bool IsOdd(int num) { ) == ; } 通 ...
- [转] MySQL索引原理
MySQL索引原理 B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉 ...
- ECS服务里或者阿里云服务器的二级域名设置方法
我们要实现的效果是,xuxinshuai.abc.com ,具体怎么实现,看下面的流程 第一步:备案域名要有,假如就是www.abc.com 第二步:网站的服务器是IIS的情况下,在部署网站时,需要设 ...
- Vue axios发送Http请求
axios 1.cnpm install axios --save 2.在vue文件中引入,import Axios from 'axios' 3.使用,Axios.get(url).then((re ...
- c++缓冲区------c++ Primer Plus
通常,通过使用缓冲区可以更高效地处理输入和输出.缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序传输给设备的临时存储工具.通常,像硬盘驱动器这样的设备以512字节(或更多)的块为单位来传输 ...
- iOS 查看代码总行数
1.打开终端 2.cd 拖入工程 回车 3.输入命令 find . "(" -name "*.m" -or -name "*.mm" -or ...
- 6w6:第六周程序填空题3
描述 下面的程序输出结果是: A::Fun A::Do A::Fun C::Do 请填空: #include <iostream> using namespace std; class A ...
- css 引入的方式有哪些, link和@import的区别是什么
有四种形式: 1.链入外部样式表,就是把样式表保存为一个样式表文件,然后在页面中用<link rel = "stylesheet" type="text/css&q ...
- uoj #297. 【CTSC2017】密钥
#297. [CTSC2017]密钥 一个密钥是一个长度为 n=2k+1n=2k+1 的字符串,它包含 11 个字母X.kk 个字母 A 和 kk 个字母 B.例如 k=3k=3 时,BAXABAB ...
- LongAdder源码学习
原文链接:https://blog.csdn.net/u011392897/article/details/60480108 LongAdder是jdk8新增的用于并发环境的计数器,目的是为了在高并发 ...