时间:2021-05-20
一:概述
项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式。
为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一个线程执行过程中可能被内核临时挂起,这就是线程切换,当内核再次切换到该线程时,之前的数据可能已被修改,不能保证原子操作。
C++11提供了个原子的类和方法atomic,保证了多线程对变量原子性操作,相比加锁机制mutex.lock(),mutex.unlock(),性能有几倍的提升。
所需头文件<atomic>
二:错误代码
//全局变量int g_num = 0;void fun(){ for (int i = 0; i < 10000000; i++) { g_num++; } return ;}int main(){ //创建线程1 thread t1(fun); //创建线程2 thread t2(fun); t1.join(); t2.join(); cout << g_num << endl; getchar(); return 1;}应该输出结果20000000,实际每次结果都不一样,总是小于该值,正是由于多线程操作同一变量而没有保证原子性导致的。
三:加锁代码
//全局变量int g_num = 0;mutex m_mutex;void fun(){ for (int i = 0; i < 10000000; 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 1;}执行结果:多次测试输出均为20000000,耗时在3.8s左右
四:atomic原子操作代码
//全局变量atomic<int> g_num = 0;void fun(){ for (int i = 0; i < 10000000; 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 1;}执行结果:多次测试输出均为20000000,耗时在1.3s左右
五:小结
c++11的原子类atomic相比使用加锁机制性能有2~3倍提升,对于共享变量能用原子类型的就不要再用加锁机制了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前面两讲《C++11并发指南二(std::thread详解)》,《C++11并发指南三(std::mutex详解)》分别介绍了std::thread和std::
std::atomic_flag std::atomic_flag是一个原子的布尔类型,可支持两种原子操作:test_and_set,如果atomic_fla
看了c++并发编程实战的内存模型部分后,一直对memory_order不太懂,今天在知乎发现了百度的brpc,恰好有关于原子操作的文档,感觉解释的很好。为了加深
在C++11以前,C++的多线程编程均需依赖系统或第三方接口实现,一定程度上影响了代码的移植性。C++11中,引入了boost库中的多线程部分内容,形成C++标
上一篇博客《C++11并发指南一(C++11多线程初探)》中只是提到了std::thread的基本用法,并给出了一个最简单的例子,本文将稍微详细地介绍std::