C++ 之多线程相关总结

news2025/1/18 8:21:31

C++ 之多线程相关总结

1.多线程相关基础知识

1.1 线程的创建和管理

1. std::thread 类:

用于创建和管理线程。通过将可调用对象(如函数、函数对象、lambda 表达式)作为参数传递给 std::thread 的构造函数,可以创建一个新的线程。

  • join() 方法会阻塞当前线程,直到被调用的线程执行完毕。如果不调用 join()detach(),程序会在 std::thread 对象析构时终止程序,因为会调用 std::terminate()
  • detach() 方法允许线程独立运行,与主线程分离,不再被 std::thread 对象管理,它会继续在后台执行直至完成或程序结束。
#include <iostream>
#include <thread>

void threadFunction() {
    std::cout << "Thread function running." << std::endl;
}

int main() {
    std::thread t(threadFunction); // 创建一个新的线程,执行 threadFunction
    t.join(); // 等待线程结束
    return 0;
}
2. 线程函数:

可以是普通函数、成员函数、函数对象或 lambda 表达式。

#include <iostream>
#include <thread>

class MyClass {
public:
    void memberFunction() {
        std::cout << "Member function running in thread." << std::endl;
    }
};

int main() {
    MyClass obj;
    std::thread t(&MyClass::memberFunction, &obj); // 调用成员函数
    t.join();
    return 0;
}

1.2 线程同步

1.互斥量(Mutex):
  • std::mutex 提供了基本的互斥机制,用于保护共享数据,防止多个线程同时访问。
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void printMessage(const std::string& message) {
    std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
    std::cout << message << std::endl;
}

int main() {
    std::thread t1(printMessage, "Hello from thread 1");
    std::thread t2(printMessage, "Hello from thread 2");
    t1.join();
    t2.join();
    return 0;
}
  • std::lock_guard 是一个 RAII 类,在构造时自动锁定互斥量,在析构时自动解锁,确保正确的锁定和解锁操作。
  • std::unique_lock 提供了更灵活的锁定方式,可以手动加锁、解锁,支持延迟锁定和所有权转移。
2.条件变量(Condition Variables):
  • std::condition_variable 允许线程等待某些条件的发生。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;

void producer() {
    for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::unique_lock<std::mutex> lock(mtx);
        dataQueue.push(i);
        std::cout << "Produced: " << i << std::endl;
        cv.notify_one(); // 通知一个等待的线程
    }
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{ return!dataQueue.empty(); }); // 等待条件满足
        int data = dataQueue.front();
        dataQueue.pop();
        lock.unlock();
        std::cout << "Consumed: " << data << std::endl;
        if (data == 9) break;
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}
  • cv.wait() 会释放锁并等待条件变量被通知,一旦收到通知,它会重新获取锁。
3. 原子操作
  • std::atomic 模板类提供了原子操作,确保操作的不可分割性,避免数据竞争。
#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> counter(0);

void increment() {
    for (int i = 0; i < 1000; ++i) {
        ++counter;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Counter value: " << counter << std::endl;
    return 0;
}

1.3 线程间通信

1.共享数据:
  • 多个线程可以通过共享数据进行通信,但需要使用互斥量或其他同步机制来保护数据。
  • 避免死锁,如避免多个线程以不同顺序获取多个锁。
2.消息传递:
  • 使用 std::promisestd::future 可以实现线程间的单向消息传递。
#include <iostream>
#include <thread>
#include <future>

int factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; ++i) {
        result *= i;
    }
    return result;
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();

    std::thread t([&prom]() {
        int result = factorial(5);
        prom.set_value(result);
    });

    std::cout << "Factorial result: " << fut.get() << std::endl;
    t.join();
    return 0;
}

1.4 高级线程工具

1. std::async 和 std::future:
  • std::async 可以异步执行函数,并返回一个 std::future 对象。
#include <iostream>
#include <future>

int add(int a, int b) {
    return a + b;
}

int main() {
    std::future<int> result = std::async(std::launch::async, add, 3, 4);
    std::cout << "Sum: " << result.get() << std::endl;
    return 0;
}
  • std::launch::async 表示函数会在另一个线程中立即执行,std::launch::deferred 表示延迟执行,直到调用 get() 时才在调用线程中执行。
2. std::packaged_task:
  • 包装可调用对象,允许将其作为任务传递,并通过 std::future 获取结果。
#include <iostream>
#include <thread>
#include <future>

int main() {
    std::packaged_task<int(int, int)> task(add);
    std::future<int> result = task.get_future();
    std::thread t(std::move(task), 3, 4);
    std::cout << "Sum: " << result.get() << std::endl;
    t.join();
    return 0;
}

2. 线程的使用:创建及管理

1.类内创建线程

  • 可以通过成员函数或者析构函数初始化或者创建线程,通过析构函数关闭/销毁线程
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>

class ThreadedClass {
private:
    std::thread workerThread;
    std::atomic<bool> stopFlag;

    // 线程函数
    void workerFunction() {
        while (!stopFlag) {
            std::cout << "Thread is running..." << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        std::cout << "Thread is stopping..." << std::endl;
    }
public:
    ThreadedClass() : stopFlag(false) {
        // 启动线程
        workerThread = std::thread(&ThreadedClass::workerFunction, this);
    }

    ~ThreadedClass() {
        // 设置停止标志
        stopFlag = true;
        if (workerThread.joinable()) {
            // 等待线程结束
            workerThread.join();
        }
    }
};

int main() {
    ThreadedClass obj;
    // 让程序运行一段时间,以便观察线程的行为
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 0;
}

2. 函数内部创建线程

  • 单独执行某个函数或者某个类的成员函数
#include <iostream>
#include <thread>
#include <chrono>

class MyClass {
public:
    // 类中的函数,将在新线程中执行
    void classFunction() {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Class function running, iteration: " << i << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
};

// 主函数,在其中创建线程执行类的函数
void mainFunction() {
    std::cout << "Main function starts." << std::endl;
    MyClass obj;

    // 创建一个新线程执行类的成员函数
    std::thread t(&MyClass::classFunction, &obj);

    // 主线程继续执行自己的任务
    for (int i = 0; i < 3; ++i) {
        std::cout << "Main function running, iteration: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    // 等待新线程执行完毕
    t.join();

    std::cout << "Main function ends." << std::endl;
}

// 函数将在新线程中执行
void newThreadFunction() {
    for (int i = 0; i < 5; ++i) {
        std::cout << "New thread: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}



int main() {
    mainFunction();

    //or
    // 创建一个新线程
    std::thread newThread(newThreadFunction);

    // 主线程继续执行自己的任务
    for (int i = 0; i < 3; ++i) {
        std::cout << "Main thread: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    // 等待新线程执行完成
    newThread.join();

    return 0;
}

----更新中。。。。。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电路笔记(信号):Python 滤波器设计分析工具pyfda

目录 滤波器设置(3步实现滤波器设计)数据分析与使用pyfda功能界面数字滤波器数学表示线性相位线性相位的定义线性相位的特性 冲击响应quartus数据加载 CG 滤波器设置(3步实现滤波器设计) pip install pyfda #安装python依赖&#xff0c;详见https://pyfda.readthedocs.io/en/la…

【15】Word:互联网发展状况❗

目录 题目​ NO2 NO3 NO4 NO5 NO6 NO7.8.9 NO7 NO8 NO9 NO10 题目 NO2 布局→页面设置→纸张&#xff1a;A4→页边距&#xff1a;上下左右→版式&#xff1a;页眉/页脚页码范围&#xff1a;多页&#xff1a;对称页边距→内侧/外侧→装订线 NO3 首先为文档应用内置…

Web前端开发技术之HTMLCSS知识点总结

学习路线 一、新闻网界面1. 代码示例2. 效果展示3. 知识点总结3.1 HTML标签和字符实体3.2 超链接、颜色描述与标题元素3.3 关于图片和视频标签&#xff1a;3.4 CSS引入方式3.5 CSS选择器优先级 二、flex布局1. 代码示例2. 效果展示3. 知识点总结3.1 span标签和flex容器的区别3.…

BUUCTF Web

[极客大挑战 2019]LoveSQL union注入 是sql注入类型 输入1 发现不是数字型注入&#xff0c;那就是字符型注入。判断字段数&#xff0c;输入order by 4 #发现错误&#xff0c;就存在三个字段数 判断回显点&#xff1a;1 union select 1,2,3 # 判断回显点为2,3 判断数据库名 …

Kinova仿生机械臂Gen3搭载BOTA 力矩传感器SeneOne:彰显机器人触觉 AI 与六维力传感的融合力量

随着工业4.0时代的到来&#xff0c;自动化和智能化成为制造业的趋势。机器人作为实现这一趋势的重要工具&#xff0c;其性能和智能水平直接影响到生产效率和产品质量。然而&#xff0c;传统的机器人系统在应对复杂任务时往往缺乏足够的灵活性和适应性。为了解决这一问题&#x…

【数据库】MySQL数据库SQL语句汇总

目录 1.SQL 通用语法 2.SQL 分类 2.1.DDL 2.2.DML 2.3.DQL 2.4.DCL 3.DDL 3.1.数据库操作 3.1.1.查询 3.1.2.创建 3.1.3.删除 3.1.4.使用 3.2.表操作 3.2.1.查询 3.2.2.创建 3.2.3.数据类型 3.2.3.1.数值类型 3.2.3.2.字符串类型 3.2.3.3.日期时间类型 3.2…

《汽车与驾驶维修》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答&#xff1a; 问&#xff1a;《汽车与驾驶维修》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第二批认定学术期刊。 问&#xff1a;《汽车与驾驶维修》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;中国机械工业联合会…

鸿蒙UI(ArkUI-方舟UI框架)-开发布局

文章目录 开发布局1、布局概述1&#xff09;布局结构2&#xff09;布局元素组成3&#xff09;如何选择布局4&#xff09;布局位置5&#xff09;对子元素的约束 2、构建布局1&#xff09;线性布局 (Row/Column)概述布局子元素在排列方向上的间距布局子元素在交叉轴上的对齐方式(…

数据结构——概述

1、什么是数据结构&#xff1f; 数据结构是计算机存储和管理数据的方式。数据必须依据某种逻辑联系组织在一起存储在计算机内&#xff0c;数据结构研究的就是这种数据的逻辑结构和数据的存储结构 2、逻辑结构——数据本身之间的关系 逻辑结构在计算机中的实现 &#xff08;1…

业务架构、数据架构、应用架构和技术架构

TOGAF(The Open Group Architecture Framework)是一个广泛应用的企业架构框架&#xff0c;旨在帮助组织高效地进行架构设计和管理。 TOGAF 的核心就是由我们熟知的四大架构领域组成:业务架构、数据架构、应用架构和技术架构。 企业数字化架构设计中的最常见要素是4A 架构。 4…

python爬虫入门(实践)

python爬虫入门&#xff08;实践&#xff09; 一、对目标网站进行分析 二、博客爬取 获取博客所有h2标题的路由 确定目标&#xff0c;查看源码 代码实现 """ 获取博客所有h2标题的路由 """url "http://www.crazyant.net"import re…

简历_使用优化的Redis自增ID策略生成分布式环境下全局唯一ID,用于用户上传数据的命名以及多种ID的生成

系列博客目录 文章目录 系列博客目录WhyRedis自增ID策略 Why 我们需要设置全局唯一ID。原因&#xff1a;当用户抢购时&#xff0c;就会生成订单并保存到tb_voucher_order这张表中&#xff0c;而订单表如果使用数据库自增ID就存在一些问题。 问题&#xff1a;id的规律性太明显、…

win32汇编环境,窗口程序中对多行编辑框的操作

;运行效果 ;win32汇编环境,窗口程序中对多行编辑框的操作 ;比如生成多行编辑框&#xff0c;显示文本、获取文本、设置滚动条、捕获超出文本长度消息等。 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;下面为asm文件 ;>>>>>>>>>>>>>&g…

【Flink系列】5. DataStream API

5. DataStream API DataStream API是Flink的核心层API。一个Flink程序&#xff0c;其实就是对DataStream的各种转换。具体来说&#xff0c;代码基本上都由以下几部分构成&#xff1a; 5.1 执行环境&#xff08;Execution Environment&#xff09; Flink程序可以在各种上下文…

探索未来:Leap Motion JavaScript框架——开启VR与手势控制的无限可能

探索未来&#xff1a;Leap Motion JavaScript框架——开启VR与手势控制的无限可能 leapjs JavaScript client for the Leap Motion Controller 项目地址: https://gitcode.com/gh_mirrors/le/leapjs 项目介绍 欢迎来到Leap Motion JavaScript框架的世界&#xff01;Lea…

PCM5142集成32位384kHz PCM音频立体声114dB差分输出DAC编解码芯片

目录 PCM5142 简介PCM5142功能框图PCM5142特性 参考原理图 PCM5142 简介 PCM514x 属于单片 CMOS 集成电路系列&#xff0c;由立体声数模转换器 (DAC) 和采用薄型小外形尺寸 (TSSOP) 封装的附加支持电路组成。PCM514x 使用 TI 最新一代高级分段 DAC 架构产品&#xff0c;可实现…

技术领衔 互学互鉴|ZASM召开2024年度技术交流会

1月16日&#xff0c;ZASM组织召开了“2024年度企业员工技术交流活动”。公司总经理&#xff0c;技术部门负责人及项目经理参加本次会议。 会上&#xff0c;公司所属各项目技术负责人围绕“三维模型切割模块的基础操作与模型发布缓存的技术演示”、“J18微型智能空中作业平台的…

UI自动化测试:异常截图和page_source

自动化测试过程中&#xff0c;是否遇到过脚本执行中途出错却不知道原因的情况&#xff1f;测试人员面临的不仅是问题的复现&#xff0c;还有对错误的快速定位和分析。而异常截图与页面源码&#xff08;Page Source&#xff09;的结合&#xff0c;正是解决这一难题的利器。 在实…

OSI七层协议——分层网络协议

OSI七层协议&#xff0c;顾名思义&#xff0c;分为七层&#xff0c;实际上七层是不存在的&#xff0c;是人为的进行划分,让人更好的理解 七层协议包括&#xff0c;物理层(我),数据链路层(据),网络层(网),传输层(传输),会话层(会),表示层(表),应用层(用)(记忆口诀->我会用表…

浅谈计算机网络04 | 现代网络需求与技术支撑

现代网络需求与技术支撑 一、网络和因特网流量的类型剖析1.1 弹性流量的自适应特征1.2 非弹性流量的刚性特征1.3 实时流量特性 二、特定领域的网络需求解析2.1 大数据环境下的网络需求分析2.2 云计算环境下的网络需求分析2.3 移动数据环境下的网络需求分析 三、QoS和QoE&#x…