CPP多线程

 

什么是多线程?

        多线程是一种允许程序同时运行多个线程的技术。每个线程可以执行不同的任务,这在处理需要并发执行的操作时(例如,处理多个客户端的网络服务器,或者图形用户界面应用程序)非常有用。多线程能够提高程序的性能和响应速度。

C++ 标准库中的 std::thread

        在 C++11 标准中,引入了 std::thread 类,使得在 C++ 中进行多线程编程变得更为简单和直接。通过 std::thread,我们可以轻松地创建和管理多个线程。

        为了更清楚地展示多线程编程的优势,创建一个示例来比较使用多线程和不使用多线程的情况。我们将编写一个程序,模拟一个计算密集型任务,例如计算一系列大素数,并分别使用单线程和多线程执行这个任务,然后比较它们的运行时间。

任务说明

我们的任务是计算从某个大数开始的 N 个素数。我们将通过以下步骤来实现:

  1. 单线程实现: 使用一个循环逐个计算 N 个素数。
  2. 多线程实现: 将任务分成 T 个部分,每个部分由一个线程来处理。
  3. 比较运行时间: 测量并比较两种实现的运行时间。

代码实现

单线程版本

        首先,我们实现一个简单的单线程版本。

#include <iostream>
#include <cmath>
#include <chrono>// 检查一个数是否是素数
bool is_prime(int num) {if (num <= 1) return false;if (num <= 3) return true;if (num % 2 == 0 || num % 3 == 0) return false;for (int i = 5; i * i <= num; i += 6) {if (num % i == 0 || num % (i + 2) == 0) return false;}return true;
}// 计算从 start 开始的 n 个素数
void find_primes(int start, int n) {int count = 0;int num = start;while (count < n) {if (is_prime(num)) {std::cout << num << " ";count++;}num++;}std::cout << std::endl;
}int main() {int start = 100000;int n = 10; // 找到 10 个素数auto start_time = std::chrono::high_resolution_clock::now();find_primes(start, n);auto end_time = std::chrono::high_resolution_clock::now();std::chrono::duration<double> duration = end_time - start_time;std::cout << "Single-threaded duration: " << duration.count() << " seconds\n";return 0;
}

多线程版本

        接下来,我们实现一个多线程版本,将任务分成多个线程来处理。

#include <iostream>
#include <cmath>
#include <chrono>
#include <thread>
#include <vector>
#include <mutex>// 检查一个数是否是素数
bool is_prime(int num) {if (num <= 1) return false;if (num <= 3) return true;if (num % 2 == 0 || num % 3 == 0) return false;for (int i = 5; i * i <= num; i += 6) {if (num % i == 0 || num % (i + 2) == 0) return false;}return true;
}std::mutex mtx; // 互斥锁用于保护输出// 线程函数,计算从 start 开始的部分素数
void find_primes_thread(int start, int n, int thread_id) {int count = 0;int num = start;while (count < n) {if (is_prime(num)) {std::lock_guard<std::mutex> guard(mtx);std::cout << "Thread " << thread_id << ": " << num << "\n";count++;}num++;}
}int main() {int start = 100000;int n = 10; // 每个线程找到 10 个素数int num_threads = 4; // 使用 4 个线程std::vector<std::thread> threads;auto start_time = std::chrono::high_resolution_clock::now();// 启动多个线程,每个线程处理一部分工作for (int i = 0; i < num_threads; ++i) {threads.emplace_back(find_primes_thread, start + i * n, n, i);}// 等待所有线程完成for (auto& t : threads) {if (t.joinable()) {t.join();}}auto end_time = std::chrono::high_resolution_clock::now();std::chrono::duration<double> duration = end_time - start_time;std::cout << "Multi-threaded duration: " << duration.count() << " seconds\n";return 0;
}

代码解释

  1. 单线程版本:

    • find_primes 函数从 start 开始计算 n 个素数,并打印结果。
    • 使用 std::chrono 计时来测量执行时间。
  2. 多线程版本:

    • find_primes_thread 函数类似于单线程版本,但它有一个额外的 thread_id 参数,用于标识线程。
    • 使用 std::mutex 来保护控制台输出,防止多线程竞争导致输出混乱。
    • main 函数中,启动 num_threads 个线程,每个线程计算 n 个素数。每个线程的起始点不同,以避免重复计算。
    • 使用 std::vector<std::thread> 来存储线程对象,并在所有线程完成后调用 join

结果比较

        将这两个版本的程序分别编译和运行,会看到它们的执行时间。在大多数情况下,多线程版本的程序会比单线程版本快得多,尤其是在处理计算密集型任务时。

g++ -std=c++11 -o single_thread single_thread.cpp
./single_thread

g++ -std=c++11 -o multi_thread multi_thread.cpp -pthread
./multi_thread 

 运行结果示例

       得到如下结果:

Single-threaded duration: 2.5 seconds
 

Thread 0: 100003
Thread 0: 100019
Thread 0: 100043
Thread 0: 100049
Thread 0: 100057
Thread 0: 100069
Thread 0: 100103
Thread 0: 100109
Thread 0: 100129
Thread 0: 100151
Thread 1: 100019
Thread 1: 100043
Thread 1: 100049
Thread 1: 100057
Thread 1: 100069
Thread 1: 100103
Thread 1: 100109
Thread 1: 100129
Thread 1: 100151
Thread 1: 100153
Thread 2: 100043
Thread 2: 100049
Thread 2: 100057
Thread 2: 100069
Thread 2: 100103
Thread 2: 100109
Thread 2: 100129
Thread 2: 100151
Thread 2: 100153
Thread 2: 100169
Thread 3: 100043
Thread 3: 100049
Thread 3: 100057
Thread 3: 100069
Thread 3: 100103
Thread 3: 100109
Thread 3: 100129
Thread 3: 100151
Thread 3: 100153
Thread 3: 100169
Multi-threaded duration: 0.00377134 seconds

结论

        通过这个示例,我们可以清楚地看到多线程编程的优势。多线程版本的程序可以显著地减少计算时间,特别是在任务可以被分割并行处理的情况下。这对于需要高性能和实时响应的应用程序来说非常重要。

        不过,需要注意的是,使用多线程也会带来一些复杂性,例如线程同步、数据竞争和死锁等问题。因此,在编写多线程程序时,必须谨慎处理这些潜在的风险。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/351105.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 2024-06-13开源项目日报Top10

根据Github Trendings的统计,今日(2024-06-13统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3非开发语言项目2Shell项目1TypeScript项目1Swift项目1PHP项目1Blade项目1JavaScript项目1从零开始构建你喜爱的技术 创建周期:2156…

MySQL数据库管理(一)

目录 1.MySQL数据库管理 1.1 常用的数据类型​编辑 1.2 char和varchar区别 2. 增删改查命令操作 2.1 查看数据库结构 2.2 SQL语言 2.3 创建及删除数据库和表 2.4 管理表中的数据记录 2.5 修改表名和表结构 3.MySQL的6大约束属性 1.MySQL数据库管理 1.1 常用的数据类…

ElementPlus非表单组件ElUpload值更新后校验不消失问题

项目场景&#xff1a; el-form表单中有一个上传组件&#xff0c;有必填校验。 问题描述 先触发表单的必填校验(点击提交按钮)&#xff0c;然后再上传文件&#xff0c;必填校验的提示一直存在&#xff0c;如果再次点击提交&#xff0c;手动触发表单校验&#xff0c;必填校验消…

JavaScript常见面试题(一)

文章目录 1. JavaScript有哪些数据类型&#xff0c;它们的区别&#xff1f;2.数据类型检测的方式有哪些3. 判断数组的方式有哪些4.null和undefined区别5.typeof null 的结果是什么&#xff0c;为什么&#xff1f;6.intanceof 操作符的实现原理及实现7.为什么0.10.2 ! 0.3&…

计算机网络(8) Finite State Machines(有限状态机)

一.建立连接&#xff08;三次握手&#xff09; 建立连接过程中的状态转换如下&#xff1a; 客户端&#xff1a; 发送SYN CLOSED >>>>>>>>>>>>>>SYN SENT(第一次握手) 接收SYNACK发送ACK …

如何看懂SparkUI?

Jobs页面 Stage页面 显示额外的指标和摘要指标&#xff1a; 摘要指标&#xff08;Summary Metrics&#xff09;统计了所有完成的任务的执行行为&#xff0c;包括执行时间、GC时间、输入输出信息等&#xff0c;并提供了最小值&#xff08;Min&#xff09;、第25百分位数&#xf…

HCIA11 网络安全之本地 AAA 配置实验

AAA 提供 Authentication&#xff08;认证&#xff09;、Authorization&#xff08;授权&#xff09;和 Accounting&#xff08;计费&#xff09;三种安全功能。 • 认证&#xff1a;验证用户是否可以获得网络访问权。 • 授权&#xff1a;授权用户可以使用哪些服务。 •…

黑马头条Minio报错non-xml response from server错误的解决方法

今天在写项目的时候&#xff0c;想测试minio上传文件功能是否正常&#xff0c; 但是每次都出现non-xml response from server的错误。 自己也在网上找了很多解决方法&#xff0c;大部分是说用户名和密码的配置问题&#xff0c;但是检查后发现并没有错误。 最后发现是自己的dock…

QT 5.14.2 应用程序打包

我们可以直接通过开发工具预览我们的程序。但是当要把开发好的程序给别人使用的时候&#xff0c;我们就需要把程序打包成可执行的exe&#xff0c;然后把这个exe文件和其他相关的文件一起发给别人&#xff0c;这样别人就可以使用了。 一、生成可独立运行的exe (一)、编译程序的…

图论(一)之概念介绍与图形#matlab

图论&#xff08;一&#xff09;之概念介绍与图形目录 前言 一、图论介绍 二、基本概念 2.1图的概念 2.2图形分类 2.3邻接矩阵 2.3.1无向图 2.3.2有向图 2.3.3有向赋权图 2.4出度&#xff08;Outdegree&#xff09; 2.5入度&#xff08;Indegree&#xff09; 3.四种…

联想电脑 调节屏幕亮度不起使用,按F5,F6,屏幕上的hotkeys进度条是在改变,但是屏幕没有一些作用的处理方法

1、查看驱动是否正常 Win键X &#xff0c;设备管理器 发现似乎挺正常的。 查看原厂驱动&#xff1a;联想电脑管家 这样看来&#xff0c;驱动是没有问题了。 2、看看设置电池模式 其实还是这个电池模式的问题导致。 如果处于养护模式的话&#xff0c;充电只在75%~80%&#x…

【Numpy】一文向您详细介绍 np.round()

【Numpy】一文向您详细介绍 np.round() 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&#xff0c;…

【大数据】计算引擎:Spark核心概念

目录 前言 1.什么是Spark 2.核心概念 2.1.Spark如何拉高计算性能 2.2.RDD 2.3.Stage 3.运行流程 前言 本文是作者大数据系列中的一文&#xff0c;专栏地址&#xff1a; https://blog.csdn.net/joker_zjn/category_12631789.html?spm1001.2014.3001.5482 该系列会成体…

【SpringCloud学习笔记】RabbitMQ(上)

1. RabbitMQ简介 官网地址&#xff1a;https://www.rabbitmq.com/ 2. 安装方式 安装前置准备&#xff1a; 此处基于Linux平台 Docker进行安装&#xff0c;前置准备如下&#xff1a; Linux云服务器 / 虚拟机Docker环境 安装命令&#xff1a; docker run \-e RABBITMQ_DEFAU…

TCP与UDP案例

udp不会做拆分整合什么的 多大就是多大

【日记】第一次养植物,没什么经验……(781 字)

正文 前两天梦见灵送的几盆植物全都死掉了。梦里好伤心。醒来与她说这件事&#xff0c;她宽慰我说&#xff0c;梦都是反着的&#xff0c;肯定能活得很好的。于是忽然记起昨天给植物换水时&#xff0c;文竹的根居然从花盆底部伸吊了出来&#xff0c;以前都没有这种情况来着&…

探索智慧校园,引领数字化教育浪潮

在21世纪的教育版图上&#xff0c;智慧校园进一步发展。这是一场深度融合信息技术与教育实践的深刻转型&#xff0c;它不仅仅是在校园里简单叠加智能设备&#xff0c;而是一种从教育理念到实践模式全方位的革新。智慧校园如同一座桥梁&#xff0c;连接着过去与未来&#xff0c;…

【OrangePiKunPengPro】 linux下编译、安装Boa服务器

OrangePiKunPengPro | linux下编译、安装Boa服务器 时间&#xff1a;2024年6月7日21:41:01 1.参考 1.boa- CSDN搜索 2.Boa服务器 | Ubuntu下编译、安装Boa_ubuntu安装boa-CSDN博客 3.i.MX6ULL—ElfBoard Elf1板卡 移植boa服务器的方法 (qq.com) 2.实践 2-1下载代码 [fly752fa…

算法设计与分析 实验1 算法性能分析

目录 一、实验目的 二、实验概述 三、实验内容 四、问题描述 1.实验基本要求 2.实验亮点 3.实验说明 五、算法原理和实现 问题1-4算法 1. 选择排序 算法实验原理 核心伪代码 算法性能分析 数据测试 选择排序算法优化 2. 冒泡排序 算法实验原理 核心伪代码 算…

【Pycharm】设置双击打开文件

概要 习惯真可怕。很多小伙伴用习惯了VsCode开发&#xff0c;或者其他一些开发工具&#xff0c;然后某些开发工具是单击目录文件就能打开预览的&#xff0c;而换到pycharm后&#xff0c;发现目录是双击才能打开预览&#xff0c;那么这个用起来就特别不习惯。 解决办法 只需一…