当前位置: 首页 > news >正文

c++11线程安全

多线程安全问题

在多个线程中共享数据时,需要注意线程安全问题。如果多个线程同时访问同一个变量,并且其中至少有一个线程对该变量进行了写操作,那么就会出现数据竞争问题。数据竞争可能会导致程序崩溃、产生未定义的结果,或者得到错误的结果。
代码如下

多线程间数据竞争代码示例:

#include <iostream>
#include <thread>
using namespace std;int shared_data = 0;
void func()
{for (int i = 0; i < 100000; i++){shared_data += 1;}
}
int main()
{for (int i = 0; i < 5; i++){shared_data = 0;thread t1(func);thread t2(func);t1.join();t2.join();cout << "第" <<i+1<<"次执行的" << "shared_data值为:" << shared_data << endl;}return 0;
}

打印的结果如下:
在这里插入图片描述
按理说,线程t1将shared_data 加100000次,线程t2执行将shared_data 加100000次,执行的结果应该时200000。但是测试了5次,每一次的打印结果都小于200000,这是因为多线程间访问出现了数据竞争问题。

以下是结合上述代码绘制的关于数据竞争的流程图

多核状态下
在这里插入图片描述

单核状态下

如果只有一个cpu内核,那么某一时刻只能有一个线程在执行,更理想的情况,如果是只有t1和t2两个线程在执行,t1执行完毕就t2执行,感觉不会发生数据竞争唉。
其实不是,以下图为例,比如说线程t1刚好读入数据shared_data的值,恰好这个时候t1的时间片用完了;轮到线程t2执行,t2执行读取shared_data的数据循环+1,比如说加到610,t2的时间片到了,将610写入内存shared_data;随后切换到t1线程,这里理论上shared_data的值该是610了,但是实际上t1中保存的上次执行值为10,于是线程t1在10的基础上进行循环+1,再次加到610,并将值写入shared_data中。但是实际上经过这两个线程的时间片执行,其值应该为1210(假设一个时间片内执行了600次加法操作)。
在这里插入图片描述

线程安全
概念:如果多线程中每一次的运行结果和单线程运行的结果始终是一样的,那么这个就可以叫做线程安全。
理解:在这里代码的理解就是线程t1执行了100000次加法操作,t2执行了100000次加法操作,最终的值就应该是200000,并且无论执行多少次,其值始终为200000。

为了避免数据竞争问题,也是为了实现线程安全,需要使用同步机制来确保多个线程之间对共享数据的安全访问。常见的同步机制包括互斥量、条件变量、原子操作等。

互斥量机制

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;int shared_data = 0;
mutex mtx;
void func()
{for (int i = 0; i < 100000; i++){mtx.lock();shared_data += 1;mtx.unlock();}
}
int main()
{for (int i = 0; i < 5; i++){shared_data = 0;thread t1(func);thread t2(func);t1.join();t2.join();cout << "第" <<i+1<<"次执行的" << "shared_data值为:" << shared_data << endl;}return 0;
}

打印结果为:
在这里插入图片描述
可以看到,执行了5次打印结果都是200000,通过互斥量实现了线程安全。

原子操作

使用atomic原子操作也可以实现线程安全。


#include <iostream>
#include <thread>
#include <atomic>
using namespace std;atomic<int> shared_data = 0;void func()
{for (int i = 0; i < 100000; i++){shared_data += 1;//shared_data.fetch_add(1);}
}
int main()
{for (int i = 0; i < 5; i++){shared_data = 0;//shared_data.store(0);thread t1(func);thread t2(func);t1.join();t2.join();cout << "第" << i + 1 << "次执行的" << "shared_data值为:" << shared_data << endl;}return 0;
}

运行结果为:
在这里插入图片描述
上述打印结果几次的执行结果都是一样的,说明原子变量atomic实现了线程安全。

http://www.xdnf.cn/news/927523.html

相关文章:

  • 图片批量格式转换工具
  • pcie 日常问答0604
  • 第一章 无刷电机(BLDC)基础知识
  • 缓冲区溢出
  • 【web笔记】JavaScript实现有动画效果的进度条
  • opencascade 小技巧截取两点间的曲线
  • iview中的table组件点击一行中的任意一点选中本行
  • 第5章:Cypher查询语言进阶
  • C++课设:简易科学计算器(支持+-*/、sin、cos、tan、log等科学函数)
  • RSA加密算法:非对称密码学的基石
  • 滚珠螺杆的预压技术是如何提高精度的?
  • Java-IO流之序列化与反序列化详解
  • 基于ANN-GA优化鲜切萝卜杀菌工艺参数
  • GICv3-PMU
  • 树莓派远程登陆RealVNC Viewer出现卡顿
  • 基于51单片机的多功能风扇控制系统
  • 判断软件是否安装,如果没有则自动安装
  • 声音信号的基频检测(python版本)
  • C++学习思路
  • DL00335-基于深度学习YOLOv11的煤矸石检测含完整数据集
  • [逆向工程] C实现过程调试与钩子安装(二十七)
  • 关于datetime获取时间的问题
  • 顶级创新者在人机互助中成为关键乘数(而并非简单地加数)
  • can转Profinet网关转换:S7-1200PLC与施耐德变频器间的通信实现
  • 测试工程师的AI测试开发进阶:LangChain在多测试领域的实战与思考
  • Go 语言 range 关键字全面解析
  • 如何从浏览器中导出网站证书
  • 蓝牙音乐(A2DP)音频延迟的一些感想跟分析,让你对A2DP体验更佳深入
  • Win11打开应用程序会弹出“打开文件-安全警告“弹框
  • Linux实战篇、第一章_02若依前后端部署之路(前端)