C++ 多线程的错误和如何避免(9)
有时候使用 std::atomic 比使用 mutexes 更高效
问题分析:使用多线程更新一些简单数据时,比如 int 型,bool 型等等,可以使用 std::atomic,这比 mutex 来得更为高效。
比如,我们一般这样用:
1 2 3 4 5 | int counter; .... mu.lock(); counter++; mu.unlock(); |
现在,我们可以这样用,
1 2 3 | std::atomic< int > counter; ... counter++; |
概念
原子操作:可以把原子操作理解为一种不需要用到互斥量加锁(无锁)技术的多线程编程方式
互斥量:多线程编程中保护共享数据
使用场合
原子操作:针对的一般都是一个变量,而不是一个代码段
互斥量:加锁一般针对一个代码段(几行代码)
std::atomic 是个类模板,用来封装某个类型的值,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <thread> #include <atomic> #include <iostream> std::atomic< int > g_mycount; void mythread() { for ( int i = 0; i < 10000000; i++) { g_mycount++; } return ; } int main() { std:: thread myobj1(mythread); std:: thread myobj2(mythread); myobj1.join(); myobj2.join(); std::cout << "两个线程执行完毕,最终的g_mycount的结果是: " << g_mycount << std::endl; } |
最后会打印出:两个线程执行完毕,最终的g_mycount的结果是: 20000000
如果不使用 std::atomic,即直接定义
1 | int g_mycount = 0; |
最后会打印出:两个线程执行完毕,最终的g_mycount的结果是: 10240079
注意:该结果是个随机值,因为两个线程读写值不受限制
另外,原子变量不可以这样定义,如下
1 | auto atm_copy = atm; |
我们需要使用 .load(),以原子方式读取 atomic 对象的值
1 | auto atm_copy = atm.load(); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?