C++线程浅谈

本篇文章我们来介绍一下C++ 多进程 多线程的技术

1.为什要学习多线程 多进程

  1. 提高程序的性能:进程和线程可以使程序并发执行,从而充分利用计算机的多核处理器和资源,提高程序的执行效率和吞吐量。

  2. 实现复杂任务:通过将任务划分为多个子任务,每个子任务由一个线程或进程处理,可以更好地组织和管理代码。这样可以降低代码的复杂性,并且易于调试和维护。

  3. 支持并发编程:进程和线程是实现并发编程的基础。并发编程可以让多个任务在同一时间段内交替执行,提供更好的用户体验,例如同时响应用户输入、处理网络请求等。

  4. 充分利用系统资源:操作系统以及底层硬件通常采用多进程或多线程的方式来管理资源。了解进程和线程的工作原理可以帮助我们更好地使用系统资源,避免资源竞争和浪费。

  5. 解决共享数据问题在多线程编程中,需要考虑到共享数据访问时可能出现的竞争条件。了解进程和线程之间的通信与同步机制可以帮助我们设计安全可靠的并发程序

例如游戏服务器 

多线程能够很好的处理多个玩家的问题 可以有效地避免阻塞

处理器处理只需要几毫秒的时间 就算玩家的请求比服务器多 也可以快速的提供服务

2.如何实现多线程

进程:执行起来的可运行程序

主线程 :每一个进程产生的一个线程

多线程实现案例:

#include <iostream>
#include <thread>// 线程函数,计算从start到end的平方和
void squareSum(int start, int end, long long& result) {result = 0;for (int i = start; i <= end; ++i) {result += i * i;}
}int main() {long long sum1 = 0, sum2 = 0;// 创建两个线程分别计算1-5和6-10的平方和std::thread thread1(squareSum, 1, 5, std::ref(sum1));std::thread thread2(squareSum, 6, 10, std::ref(sum2));// 等待两个线程执行完毕thread1.join();thread2.join();// 输出结果std::cout << "Sum of squares from 1 to 5: " << sum1 << std::endl;std::cout << "Sum of squares from 6 to 10: " << sum2 << std::endl;std::cout << "Total sum: " << sum1 + sum2 << std::endl;return 0;
}

在这个案例中,我们使用std::thread库创建了两个线程,分别计算从1到5和从6到10的平方和。每个线程将自己的结果存储在一个引用参数中。然后,通过调用join()函数等待两个线程执行完毕,并将最终结果输出到控制台。

需要注意的是,在多线程编程中,我们需要考虑到共享数据访问时可能出现的竞争条件。为了避免潜在的问题,可以使用互斥锁(std::mutex)或其他同步机制来确保线程安全。

3.互斥锁 线程池等知识

互斥锁(Mutex)是一种用于多线程编程的同步机制,它可以防止多个线程同时访问共享资源导致的竞争条件。

 

线程池(Thread Pool)是一种用于管理和复用线程的技术,它可以提供更高效的线程管理和任务调度机制。

在多线程编程中,创建和销毁线程是比较耗费资源的操作。而且,频繁地创建和销毁线程可能导致系统性能下降。线程池的思想就是将一组预先创建好的线程放入一个池中,并维护这些线程的生命周期。当有任务需要执行时,从线程池中获取一个空闲的线程来执行任务,完成后再放回线程池以便复用。

互斥锁代码实例:

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx; // 定义一个互斥锁int sharedData = 0;void updateData() {std::lock_guard<std::mutex> lock(mtx); // 使用lock_guard自动管理锁的加解锁过程++sharedData;
}int main() {std::thread thread1(updateData);std::thread thread2(updateData);thread1.join();thread2.join();std::cout << "Shared data: " << sharedData << std::endl;return 0;
}

线程池代码实例:

#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>class ThreadPool {
public:ThreadPool(size_t numThreads) : stop(false) {for (size_t i = 0; i < numThreads; ++i) {threads.emplace_back([this] {while (true) {std::function<void()> task;// 获取任务{std::unique_lock<std::mutex> lock(queueMutex);condition.wait(lock, [this]{ return stop || !tasks.empty(); });if (stop && tasks.empty()) {return;}task = std::move(tasks.front());tasks.pop();}// 执行任务task();}});}}template<typename F, typename... Args>void enqueue(F&& f, Args&&... args) {// 将任务包装成函数并添加到队列中{std::unique_lock<std::mutex> lock(queueMutex);tasks.emplace([f, args...] { f(args...); });}condition.notify_one(); // 唤醒一个线程来执行任务}~ThreadPool() {{std::unique_lock<std::mutex> lock(queueMutex);stop = true;}condition.notify_all();for (std::thread& thread : threads) {thread.join();}}private:std::vector<std::thread> threads;std::queue<std::function<void()>> tasks;std::mutex queueMutex;std::condition_variable condition;bool stop;
};// 示例任务函数
void taskFunction(int id) {std::cout << "Task " << id << " executed by thread " << std::this_thread::get_id() << std::endl;
}int main() {ThreadPool pool(4); // 创建一个大小为4的线程池// 添加10个任务到线程池中for (int i = 0; i < 10; ++i) {pool.enqueue(taskFunction, i);}return 0;
}

在上述示例中,我们首先定义了一个ThreadPool类,其中包含了一个存储线程对象的std::vector容器和一个任务队列(使用std::queue),以及相应的互斥锁和条件变量用于线程同步。

在构造函数中,我们根据指定的线程数量创建了对应数量的线程,并通过Lambda表达式定义了每个线程要执行的工作。每个线程循环地从任务队列中获取任务并执行,直到停止标志被设置为true。

enqueue()函数中,我们将需要执行的任务封装成一个函数,并添加到任务队列中。之后通过调用condition.notify_one()唤醒一个空闲的线程来执行该任务。

最后,在析构函数中,我们设置停止标志为true,并通过调用condition.notify_all()来通知所有线程停止运行。然后等待每个线程结束运行。

 

总结:

1.常用的线程函数  std::thread  std::this_thread::sleep_for  std::mutex.....

2.掌握多线程编程知识 能够帮助我们实现大型项目的制作 大并发和百万级服务器  掌握线程池  互斥锁 原子锁等知识 能够完美的实现资源节约的功能

好了 本篇文章就到这里 在这里我想向大家推荐一个课程:

 https://xxetb.xetslk.com/s/2PjJ3T

 

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

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

相关文章

Windows搭建docker+k8s

安装Docker Desktop 从官网下载&#xff0c;然后直接安装即可&#xff0c;过程很简单&#xff0c;一直Next就行。 有一点需要注意就是要看好对应的版本&#xff0c;因为后边涉及到版本的问题。 https://www.docker.com/products/docker-desktop 安装完成&#xff0c;双击图…

Linux_动静态库

动态库 静态库 刚开始学编程时&#xff0c;需要下载一个环境&#xff08;vs2019&#xff09;&#xff0c;这个环境包括编译器和标准库&#xff0c;标准头文件。那么什么是库呢&#xff0c;库和头文件有什么关系呢&#xff1f; 头文件里面放的函数声明&#xff0c;库文件里面放…

Spring Boot3自定义异常及全局异常捕获

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 目的 主要步骤 定义自定义异常类 创建全局异常处理器 手动抛出自定义异常 前置条件 已经初始化好一个…

建立网站的主要步骤

建立网站的主要步骤 最近&#xff0c;我无意中发现了一个异常有用的资源&#xff0c;它提供了一种令人惊叹的机会&#xff0c;可以获取免费的域名和SSL证书。这个资源位于https://www.rainyun.com/z22_&#xff0c;我迫不及待地要与你分享这个宝贵的发现。 在这个数字时代&…

ARM:AI 的翅膀,还能飞多久?

ARM&#xff08;ARM.O&#xff09;于北京时间 2024 年 2 月 8 日上午的美股盘后发布了 2024 年第三财年报告&#xff08;截止 2023 年 12 月&#xff09;&#xff0c;要点如下&#xff1a; 1、整体业绩&#xff1a;收入再创新高。ARM 在 2024 财年第三季度&#xff08;即 23Q4…

第二篇【传奇开心果微博系列】Python微项目技术点案例示例:成语接龙游戏

传奇开心果微博系列 系列微博目录Python微项目技术点案例示例系列 微博目录一、微项目目标二、雏形示例代码三、扩展整体思路四、玩家输入示例代码五、成语判断示例代码六、回答判断示例代码七、电脑判断示例代码八、游戏结束示例代码九、界面优化示例代码十、扩展成语库示例代…

大更新!gpt加入记忆功能,可以记忆自己的提问啦!

2月14日凌晨&#xff0c;OpenAI在官网宣布&#xff0c;正在测试ChatGPT记住用户提问内容的能力&#xff0c;同时可以自由控制其内存。 该功能使用户不必频繁地提问相同的内容&#xff0c;ChatGPT都将记住那些内容并对长对话、个性化聊天等&#xff0c;例如&#xff0c;写长文小…

实现JNDI

实现JNDI 问题陈述 Smart Software Developer Ltd.想要开发一款Web应用程序,它使用servlt基于雇员ID显示雇员信息,雇员ID由用户通过HTML用户界面传递。雇员详细信息存储在Employee_Master表中。另外,Web应用程序应显示网站被访问的次数。 解决方案 要解决上述问题,需要执…

情报搜集神器:theHarvester 保姆级教程(附链接)

一、介绍 theHarvester 是一款用于信息搜集&#xff08;OSINT&#xff09;的开源工具&#xff0c;它旨在通过收集公开可用的信息&#xff0c;帮助安全专业人员、渗透测试人员和研究人员获取目标域的有用信息。theHarvester 主要用于搜集电子邮件地址、子域名、主机名、虚拟主机…

双指针练习题复写零

复写零 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改&#xff0c;不要从函数返回任何东西。 示例 1&…

Xubuntu16.04系统中修改系统语言和系统时间

1.修改系统语言 问题&#xff1a;下图显示系统语言不对 查看系统中可用的所有区域设置的命令 locale -a修改/etc/default/locale文件 修改后如下&#xff1a; # File generated by update-locale LANG"en_US.UTF-8" LANGUAGE"en_US:en"LANG"en_US…

基于Robei EDA--实现串口数据包接收

一、定义串口传输协议帧 控制字的数据大小为一字节&#xff0c;定义帧头为&#xff08;0xFE 0xDF&#xff09;帧尾为&#xff08;0xEF&#xff09; 模块框图 内模块&#xff1a;串口接收&#xff0c;output&#xff1a;8位data 串口命令&#xff1a;对单字节数据接收进行缓存…