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

 

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

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

相关文章

Acwing---842.排列数字

排列数字 1.题目2.基本思想3.代码实现 1.题目 给定一个整数 n&#xff0c;将数字 1∼n排成一排&#xff0c;将会有很多种排列方法。 现在&#xff0c;请你按照字典序将所有的排列方法输出。 输入格式 共一行&#xff0c;包含一个整数 n。 输出格式 按字典序输出所有排列方案…

Java安全 URLDNS链分析

Java安全 URLDNS链分析 什么是URLDNS链URLDNS链分析调用链路HashMap类分析URL类分析 exp编写思路整理初步expexp改进最终exp 什么是URLDNS链 URLDNS链是Java安全中比较简单的一条利用链&#xff0c;无需使用任何第三方库&#xff0c;全依靠Java内置的一些类实现&#xff0c;但…

读千脑智能笔记12_阻止人类灭绝

1. 阻止人类灭绝 1.1. 宇宙中唯一知道这些的物体&#xff0c;唯一知道宇宙存在的物体&#xff0c;是我们的大脑 1.2. 如果没有关于某个事物的知识&#xff0c;我们能说这个事物就一定存在吗&#xff1f; 1.2.1. 我们的大脑扮演着这样一个独特的角色&#xff0c;这很令人着迷…

使用matplotlib库在Python中绘制散点图

使用matplotlib库在Python中绘制散点图&#xff0c;展示了两个月份的气温变化。 # coding: utf-8 from matplotlib import pyplot as plt # 导入matplotlib库中的pyplot模块&#xff0c;并重命名为plt from matplotlib import font_manager # 导入font_manager模块&#xff…

代码随想录刷题笔记 DAY 23 | 修剪二叉搜索树 No.669 | 将有序数组转换为二叉搜索树 No.108 | 把二叉搜索树转换为累加树 No.538

文章目录 Day 2301. 修剪二叉搜索树&#xff08;No. 669&#xff09;1.1 题目1.2 笔记1.3 代码 02. 将有序数组转换为二叉搜索树&#xff08;No. 108&#xff09;2.1 题目2.2 笔记2.3 代码 03. 把二叉搜索树转换为累加树&#xff08;No. 538&#xff09;3.1 题目3.2 笔记3.3 代…

Linux_进程地址空间

我们用c语言写的程序&#xff0c;经过编译后形成可执行程序存放在硬盘。当运行该程序时&#xff0c;操作系统将该程序加载到内存中&#xff0c;创建进程控制块&#xff0c;变为进程&#xff0c;然后开始执行该程序。大家是否想过&#xff0c;操作系统是如何加载的呢&#xff1b…

有状态DHCPv6快速模式配置及EUI-64介绍

正文共&#xff1a;1024 字 15 图&#xff0c;预估阅读时间&#xff1a;3 分钟 我们现在已经熟悉了IPv6的地址架构&#xff08;IPv6地址架构一本通&#xff09;&#xff0c;掌握了IPv6地址的手工配置方式&#xff08;IPv6从入门到精通&#xff09;和DHCPv6有状态地址配置&#…

01.数据结构篇-链表

1.找出两个链表的交点 160. Intersection of Two Linked Lists (Easy) Leetcode / 力扣 例如以下示例中 A 和 B 两个链表相交于 c1&#xff1a; A: a1 → a2↘c1 → c2 → c3↗ B: b1 → b2 → b3 但是不会出现以下相交的情况&#xff0c;因为每个节点只有一个…

Peter算法小课堂—区间模型(2)

上次咋们讲了前两个区间模型&#xff1a;1.最大不重叠区间数 2.不重叠区间最少分组数。今天我们就学习&#xff1a;最小区间覆盖问题、区间重叠最厚层数&#xff01; 最小区间覆盖 先看三道题 那么&#xff0c;第1题&#xff0c;它是浮点数的题&#xff0c;也就要求首尾相同。…

通过增加缓存优化斐波那契递归的冗余计算

一、python 斐波那契数列的递归实现存在大量的冗余计算。例如&#xff0c;为了计算fib(n)&#xff0c;我们需要计算fib(n-1)和fib(n-2)&#xff0c;但是在计算fib(n-1)的过程中&#xff0c;我们又会重复计算fib(n-2)。当n的值很大时&#xff0c;这种冗余计算会消耗大量的计算资…

机器学习:ROC曲线笔记

ROC曲线&#xff08;Receiver Operating Characteristic Curve&#xff09;是一种用于评估二分类模型性能的图形化工具&#xff0c;主要用于展示在不同阈值&#xff08;Threshold&#xff09;下模型的真阳性率&#xff08;True Positive Rate&#xff0c;TPR&#xff09;和假阳…

最新在线看4K高清电影网站推荐

随着互联网技术的发展&#xff0c;观看高清电影已经不再是难事。这里我为大家分享几个最新的在线看4K高清电影网站&#xff0c;让您在家就能享受到极致观影体验。 通过下面这个即可 1. 【超清影视】 【超清影视】是国内新兴的4K高清电影网站&#xff0c;拥有海量的影片资源&a…

【送书福利-第三十一期】《区块链安全理论与实践(安全技术经典译丛)》

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

幻兽帕鲁游戏官方更新了版本,联机时提示版本不适用,无法加入,怎么办?

如果你在登录游戏的时候提示&#xff1a;您正在尝试加入的比赛正在运行不兼容的游戏版本。请尝试升级游戏版本。此时就说明你需要更新部署在服务器内的幻兽帕鲁了。 1、如果你使用幻兽帕鲁应用模板部署游戏&#xff0c;那么可以选择使用游戏配置面板一键更新。 2、如果你使用一…

使用Xcode 真机无线调试

1.iPhone和Xcode连在同一WIFI下 2.打开Xcode 顶部菜单 选中Window -> Device and Simulators 3.选中Connect via network (注意&#xff1a;勾选前还要用数据线连接,测试机要设置密码,出弹窗的话要点击信任) 真机设备旁边出现小地球 就代表成功了

【ES】--ES集成热更新自定义词库(字典)

目录 一、问题描述二、具体实施1、Tomcat实现远程扩展字典2、验证生效3、ES配置远程扩展字典4、为何不重启ES能实现热更新 一、问题描述 问题现象: 前面完成了自定义分词器词库集成到ES中。在实际项目中词库是时刻在变更的&#xff0c;但又不希望重启ES&#xff0c;对此我们应…

书生·浦语大模型第四课作业

基础作业&#xff1a; 构建数据集&#xff0c;使用 XTuner 微调 InternLM-Chat-7B 模型, 让模型学习到它是你的智能小助手&#xff0c;效果如下图所示&#xff0c;本作业训练出来的模型的输出需要将不要葱姜蒜大佬替换成自己名字或昵称&#xff01; 1.安装 # 如果你是在 Int…

备战蓝桥杯---组合数学基础1

让我们来几道高中的组合题吧&#xff1a; 1.我们一定有n个向下&#xff0c;为 2.我们挑最大的两个&#xff0c;条件是他们奇偶性相同&#xff0c;为2*A10,2; 3.用捆绑法即可。 4.我们用隔板法&#xff0c;为 5.问题等价于23个相同的球放到3个盒子里&#xff0c;每个盒子至少…

如何使用ProcessStomping在可执行程序的字段部分执行Shellcode

关于ProcessStomping ProcessStomping是一款功能强大的Shellcode代码执行工具&#xff0c;该工具允许广大研究人员在目标可执行程序的指定字段部分执行Shellcode代码。 ProcessStomping实际上是Process Overwriting项目的一个升级版本&#xff0c;并且能够向目标应用程序的指…

2000-2021年县域指标统计数据库

2000-2021年县域统计数据库 1、时间&#xff1a;2000-2021年 2、来源&#xff1a;县域统计年鉴 3、范围&#xff1a;2500县 5、指标&#xff1a; 地区名称、年份、行政区域代码、所属城市、所属省份、行政区域土地面积平方公里、乡及镇个数个、乡个数个、镇个数个、街道办…