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

结论

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

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

20. mediasoup服务器的布署与使用

Mediasoup Demo部署 架构服务分析 服务端提供3个服务&#xff1a; 1.www服务&#xff0c;浏览器通过访问服务器目录获取客户端代码&#xff0c;通过V8引擎&#xff0c;启动底层WebRTC 2.nodejs提供websocket服务和http服务&#xff0c;用于信令交互 3.Mediasoup C提供的流媒体…

分类预测 | Matlab实现基于Transformer多特征分类预测/故障诊断

分类预测 | Matlab实现基于Transformer多特征分类预测/故障诊断 目录 分类预测 | Matlab实现基于Transformer多特征分类预测/故障诊断分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现Transformer多特征分类预测/故障诊断&#xff0c;运行环境Matlab2023b及以…

代码随想录——组合总数Ⅲ(Leetcode216)

题目链接 回溯 class Solution {List<List<Integer>> res new ArrayList<List<Integer>>();List<Integer> list new ArrayList<Integer>();public List<List<Integer>> combinationSum3(int k, int n) {backtracking(k, …

【数字化转型,从BI开始】论BI在数字化转型的作用

引言&#xff1a;在新的市场和用户需求、传统经济增长缓慢、疫情黑天鹅事件等多重因素的影响下&#xff0c;企业遭遇了集体性的困境&#xff0c;而数字化转型就是各领域企业寻找出的应对方式。数字化转型包含的三维度之一数据力&#xff0c;就包含数据治理和数据分析&#xff0…

ubuntu搭建java开发环境IDEA版

一.安装 OpenJDK 更新包列表&#xff1a; sudo apt update安装 OpenJDK&#xff1a; 你可以选择安装不同版本的 OpenJDK&#xff0c;例如 11 或 17&#xff0c;这个是安装 OpenJDK 11 的命令&#xff1a; sudo apt install openjdk-11-jdk验证安装&#xff1a; 安装完成后…

DETR开篇之作

1. 论文背景和动机 背景&#xff1a; 传统的物体检测方法&#xff08;如Faster R-CNN等&#xff09;通常依赖复杂的多阶段 pipeline&#xff0c;包括区域候选生成、特征提取和后处理步骤。这些方法尽管有效&#xff0c;但复杂度高且难以端到端训练。 动机&#xff1a; DETR的提…

头歌资源库(7)汉诺塔(循环)

一、 问题描述 二、算法思想 初始化三个柱子A、B、C&#xff0c;初始时所有的盘子都在柱子A上。对于从1到N&#xff08;N表示盘子的数量&#xff09;的每一个数字i&#xff0c;执行以下循环&#xff1a; a. 如果i是偶数&#xff0c;则将柱子B视为目标柱子&#xff0c;柱子C视为…

三分钟带你手把手安装 GoldWave

goldwave绿色版是一款非常不错的数字音频编辑处理软件&#xff0c;绿色制作&#xff0c;无需安装即可使用&#xff0c;拥有录制、编辑、音频处理、恢复、增强和转换等多种功能&#xff0c;不管是最简单的录制、编辑&#xff0c;还是复杂的的音频处理、恢复、增强和转换&#xf…

如何看懂SparkUI?

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

计算机组成原理之浮点四则运算

文章目录 浮点加减运算浮点乘法运算浮点除法运算浮点运算器的流水原理习题 浮点加减运算 总的来说&#xff0c;分为四个步骤&#xff1a; &#xff08;1&#xff09;0操作数检查 &#xff08;2&#xff09;比较阶码大小并完成对阶 &#xff08;3&#xff09;尾数进行加或者减操…

扫地机LiDAR形态之美

石头扫地机V20 LiDAR: Flash光源和Spot光源切换 图来自 Robot森 LiDAR(Light Detection and Ranging,激光雷达)技术在扫地机器人中的应用,不仅提升了机器的智能性和实用性,还展现了一种科技与艺术的融合之美。 一、外观设计的精致性 紧凑与轻巧:扫地机器人的LiDAR传感器…

【学习笔记】centos7安装mysql相关事项

究极恶心的体验 依赖要按照顺序安装&#xff0c;有些依赖安装位置也不同 非常细节 mysql安装包&#xff1a;mysql官网下载地址 centos7选择Red Hat Enterprise Linux 7 / Oracle Linux 7 (x86, 64-bit), RPM Bundle 下载版本自选 安装视频教程&#xff1a;centos7.5安装mysql …

板凳----《Linux/Unix系统编程手册》读书笔记24章

D 24章 进程的创建 425 24.1 fork()、exit()、wait()以及execve()的简介 425 . 系统调用fork()允许父进程创建子进程 . 库函数exit(status)终止进程&#xff0c;将进程占用的所有资源归还内核&#xff0c;交其进行再次分配。库函数exit()位于系统调用_exit()之上。在调用fo…

2024上半年软考---江苏考区最先公布成绩

经历了考试之后&#xff0c;最期待的就是考试成绩的公布了&#xff0c;最好的成绩是45、45、45.只要过了分数线就满足了。下面我们来看看各大考区的分数的公布时间。 提前说下江苏考区的时间比较早&#xff0c;我就是江苏考区的&#xff0c;希望本次可以顺利通过考试。 2024年…

【全栈实战】大模型自学:从入门到实战打怪升级,20W字总结(一)

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本栏讲解【全栈实战】大模型自学&#xff1a;从入门到实战打怪升级。 &#x1f514;专栏持续更新&#xff0c;适合人群&#xff1a;本科生、研究生、大模型爱好者&#xff0c;期…

React 中的事件处理

React 中是如何处理事件的&#xff0c;现在下面简单的一段代码&#xff1a; export default function App() {const AList lazy(()>import(./List.js))const r useRef(null) const [show, setShow] useState(false);return (<><button onFocus{()>{setShow…

数据可视化案例

数据可视化案例 使用豆瓣电影中的数据来进行可视化&#xff0c;网址&#xff1a;豆瓣电影 Top 250 (douban.com) 一、网页数据分析 我们需要爬取的是豆瓣电影Top250网页每一页的电影名称、图片链接、导演、年份、国家、电影类型、电影评分这些数据。 在待爬取的网页中&#x…

17岁中专女生,闯进全球数学竞赛12强

今年阿里的数学竞赛结果出来了&#xff0c;在榜单的前列包含一个 17 岁的中专女生。 在 2018 年时&#xff0c;阿里巴巴达摩院发起了一个国际数学竞赛&#xff0c;基本每年举办一次&#xff0c;参赛不设报名条件&#xff0c;向全球所有数学爱好者开放&#xff0c;竞赛由阿里创…

AOSP平台开发的利器——Android Studio for Platform

Android Studio for Platform (ASfP) 是一个为使用 Soong 构建系统构建的 Android 开源项目&#xff08;AOSP&#xff09;平台开发者而设计的 Android Studio IDE 版本。与标准 Android Studio 不同&#xff0c;ASfP 具有多语言支持&#xff0c;可以在同一 IDE 中编写 C、Kotli…

java高级——Arrays工具类(包含核心的归并和二分排序以及多个底层知识点)

java高级——Arrays工具类 前情提要文章介绍提前了解的知识点1 二分查找思想 Arrays常用方法介绍&#xff08;8大类&#xff09;1. 创建数组1.1 copyOf&#xff08;&#xff09;1.2 copyOfRange&#xff08;&#xff09;1.3 fill&#xff08;&#xff09; 2. 数组转集合&#x…