C++多线程不加锁操作同一个整数
#include <iostream> #include <thread> #include <vector> #include <chrono> #include <atomic> using namespace std; int num = 0; //volatile int num = 0; //atomic<int> num = 0; void add() { int times = 0; for (int i = 0; i < 10000; ++i) { //std::cout << std::this_thread::get_id() << ":" << num++ << std::endl; num++; this_thread::sleep_for(chrono::milliseconds(0)); times++; } std::cout << "thread id: [" << std::this_thread::get_id() << "] run times:" << times << std::endl; } int main() { vector<thread> vects; for (int i = 0; i < 2; ++i) { vects.push_back(thread(add)); } for (auto& t : vects) { t.join(); } std::cout << "main thread, final num: " << num << std::endl; }
上面是两线程同时对num执行自加操作, 实际输出结果:
thread id: [29524] run times:10000
thread id: [30444] run times:10000
main thread, final num: 17766
两个进程每个线程执行对同一个数连加10000次, 加锁或使用atomic的值应该是20000.
网上有说单个数值可以不用加锁的原因是, 单条cpu指令取这个整数值是不会出错的. 他们推荐类对象或struct要加锁, 比如struct strTest{int a, int b}, 取strTest数据, 需要两条指令才能完成, 先取a值, 再取b值, 多线程时会有其它指令在中间正好修改了b值.
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义