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

【和春笋一起学C++】(四十五)多线程编程中的线程安全问题

在C++编程中,经常会用到多线程编程以提高程序的运行效率,使用多线程编程时最重要的是要解决线程安全问题。

非线程安全(Non-Thread-Safe):代码在多线程并发访问时可能导致数据竞争或状态不一致。这类代码或对象在单线程环境下可以正常工作,但在多线程环境下需要额外的同步机制(如锁、原子操作等)来保证安全性。

在上篇文章《【和春笋一起学C++】(四十四)随机行走理论——编程实现》中使用的rand()函数也是非线程安全的,在单线程程序中使用是没有问题的,但在多线程程序中则会导致数据竞争问题。因rand()函数内部使用静态变量存储状态,多线程使用rand()函数势必会导致内部状态竞争,导致其状态被破坏。解决办法是不用rand()函数来产生随机数,用<random>库来代替,因为<random>库是线程安全的。

将随机行走理论的程序改成多线程程序,对比单线程的程序,看看运行效率提升了多少。

使用上篇文章 《【和春笋一起学C++】(四十四)随机行走理论——编程实现》中的Cvector类,单线程程序的代码如下:

#include <iostream>
#include <cmath>
#include <random>
#include "Cvector.h"
#include <opencv2/opencv.hpp>
using namespace cv;std::vector<int> vector_steps;
std::ofstream outf("steps.txt");void GetSteps()
{using namespace std;///获取非确定性种子std::random_device rd;///组合多个种子,使随机性更好std::seed_seq seed{ rd(), rd(), rd() };///初始化随机数引擎std::mt19937 gen(seed);///定义均匀分布范围[1, 360]std::uniform_int_distribution<int> dist(1, 360);///生成随机数Cvector initial_v;int angle;int total_steps = 0;for (int i = 0; i < 200000; i++){///获取随机角度angle = dist(gen);Cvector rand_angle(2, angle);initial_v = initial_v + rand_angle;if (sqrt(initial_v.x*initial_v.x + initial_v.y*initial_v.y) > 50){total_steps = i + 1;break;}}vector_steps.push_back(total_steps);outf << total_steps << endl;return;
}int main()
{using namespace std;double time_start;double time_end;time_start = (double)getTickCount();for (int i = 0; i < 1000; i++){GetSteps();}outf.close();time_end = (double)getTickCount();cout << "计算模块耗时: " << (time_end - time_start) * 1000 / getTickFrequency() << "毫秒" << endl;return 0;
}

单线程程序的运行时间为232ms,将上述代码改成多线程,如下:

#include <iostream>
#include <cmath>
#include <random>
#include <thread>
#include <mutex>
#include "Cvector.h"
#include <opencv2/opencv.hpp>
using namespace cv;std::vector<int> vector_steps;
std::ofstream outf("steps.txt");
std::mutex mtx;
void GetSteps()
{using namespace std;///获取非确定性种子std::random_device rd;///组合多个种子,使随机性更好std::seed_seq seed{ rd(), rd(), rd() };///初始化随机数引擎std::mt19937 gen(seed);///定义均匀分布范围[1, 360]std::uniform_int_distribution<int> dist(1, 360);///生成随机数Cvector initial_v;int angle;int total_steps = 0;for (int i = 0; i < 200000; i++){///获取随机角度angle = dist(gen);Cvector rand_angle(2, angle);initial_v = initial_v + rand_angle;if (sqrt(initial_v.x*initial_v.x + initial_v.y*initial_v.y) > 50){total_steps = i + 1;break;}}lock_guard<mutex> lock(mtx);///进入作用域时自动加锁vector_steps.push_back(total_steps);// 临界区操作outf << total_steps << endl;// 临界区操作return;
}///离开作用域时自动解锁int main()
{using namespace std;double time_start;double time_end;time_start = (double)getTickCount();for (int i = 0; i < 200; i++){thread t1(GetSteps);thread t2(GetSteps);thread t3(GetSteps);thread t4(GetSteps);thread t5(GetSteps);t1.join();t2.join();t3.join();t4.join();t5.join();}outf.close();time_end = (double)getTickCount();cout << "多线程计算模块耗时: " << (time_end - time_start) * 1000 / getTickFrequency() << "毫秒" << endl;return 0;
}

程序说明:

程序创建了5个线程,所以for循环只需要循环200次就能得到1000个数据,多线程的程序运行时间为137ms。可以打开输出文件steps.txt确认下数据数目是否为1000个。上述多线程程序和单线程程序运行的结果是相同的,但多线程比单线程节省了大约41%的时间(注:此处的运行时间因计算机的性能不同而有所差异)。

在多线程编程中,除了内部状态竞争(rand()函数)会引起线程安全问题,数据竞争也会引起线程安全问题。数据竞争指的是多个线程同时读写同一共享变量,且没有同步机制时,会导致数据竞争。如上述程序中的vector_steps和outf都是共享变量,在多线程并发访问这两个变量时,就会导致数据竞争。通过使用互斥锁(Mutex)保护共享数据,从而避免数据竞争导致线程安全问题。

上面多线程程序中lock_guard<mutex> lock(mtx);语句用于自动管理互斥锁生命周期,上述代码中通过lock_guard包裹临界区代码,防止数据竞争。

lock_guard是C++11 引入的模板类,构造时自动调用 mtx.lock()锁定互斥量;析构时(离开作用域时)自动调用mtx.unlock()解锁,确保锁不会遗漏释放。

http://www.dtcms.com/a/400456.html

相关文章:

  • 80s网站建设工作室wordpress恶意代码
  • 【CTF-Web考点讲解 jwt】
  • 昆明网站开发的公司竞价推广思路
  • 开发网站的经济可行性阿里巴巴网站怎么做全屏分类
  • 弹窗广告最多的网站wordpress 图片热点
  • CentOS7安装MySQL5.7服务
  • SAP提出让步以解决欧盟反垄断担忧,避免调查与罚款
  • 湛江自做网站seo综合查询工具下载
  • 邱县seo整站排名盗取wordpress源码
  • 个人网站建设详细教程php网站开发公司
  • 异常的统一处理
  • 代码共享网站wordpress mnews
  • Win11在哪设置禁用网络连接?Win11禁用网络连接步骤介绍
  • 旅游网站建设的规模设想建筑公司会计账务处理
  • 十一、Linux中RCU的实现以及内核抢占控制函数
  • 政务网站建设目的_意义做营销怎样才能吸引客户
  • 安徽宿州住房与建设网站济南市建设工程招标投标协会网站
  • 做外贸网络推广网站河南seo推广平台
  • 怀化网站优化哪个好php做网站示例
  • 用tornado做网站qq空间网站是多少
  • mvc电子商务网站开发微信app
  • 网站设计师主要做什么wordpress积分查看
  • 厘清大小端:分清数值轴、地址轴与书写轴
  • 保定做网站电话北京市住房建设投资中心网站
  • 如何优化唯品会库存API性能?
  • 四川住房和城乡建设部官方网站WordPress文章不置顶
  • 建设图片展示网站网站服务器指的是什么
  • 卖东西的网站怎么建设app开发需要哪些软件
  • 分析可口可乐网站建设的目的男女做爰视频网站在线
  • 网站模板平台资源电子商务网站功能模块