CPP多线程

2024-06-16 17:04
文章标签 多线程 cpp

本文主要是介绍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

结论

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

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

 

这篇关于CPP多线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067026

相关文章

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

Python多进程、多线程、协程典型示例解析(最新推荐)

《Python多进程、多线程、协程典型示例解析(最新推荐)》:本文主要介绍Python多进程、多线程、协程典型示例解析(最新推荐),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 目录一、multiprocessing(多进程)1. 模块简介2. 案例详解:并行计算平方和3. 实现逻

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同