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. ...
随机推荐
- 删除当前文件夹的bat工具
@echo off:11set /p path=Please enter delete filepath:del /f /s /q %path%rd /q /s %path%goto 11pause
- rtabmap and rtabmap_ros make error(rtabmap编译错误)
Build from source following README.nd in rtabmap_ros rtabmap make error Error 1 make[2]: *** No rule ...
- HDP 中 yarn 和 MR2 的配置
以下说明均以集群中 slave 结点的配置为 48G内存,12块硬盘,12核(core) CPU 为例. 在 Yarn 中,一个 Container 是一个基础的包含内存和CPU 的单元.为了较好的平 ...
- oracle取order by的第一条数据
SELECT * FROM (SELECT * FROM TABLE_NAME ORDER BY COL1) WHERE ROWNUM = 1; 备注: 1.不能给 (SELECT * FROM TA ...
- tcp连接过程中的三次握手和四次挥手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手握手建立连接 @第一次握手: 建立连接是,客户端A发送SYN包到服务器B,并进入SYN_SEND状态,等待B确认. @第二次握手: 服务 ...
- 【BZOJ4555】[TJOI&HEOI2016]求和 斯特林数+NTT
Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ∗ S(i ...
- 【bzoj4869】[Shoi2017]相逢是问候 线段树+扩展欧拉定理
Description Informatikverbindetdichundmich. 信息将你我连结.B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以 分为两 ...
- django日期查询出现UTC日志转换CONVERT_TZ出错的问题
select CONVERT_TZ(NOW(), 'UTC', 'UTC') 出现NULL值, 原因是MySQL少了时区表: SELECT * FROM mysql.time_zone; SELECT ...
- Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表)
Leetcode 25. Reverse Nodes in k-Group 以每组k个结点进行链表反转(链表) 题目描述 已知一个链表,每次对k个节点进行反转,最后返回反转后的链表 测试样例 Inpu ...
- 前端模块开发的基础代码,兼容amd,cmd标准,也可以直接使用window来引用对象
(function(global, factory) { if (typeof define === 'function' && define.amd) { define(functi ...