首页 > 编程语言 >C++ 中的多线程编程:从基础到实战

C++ 中的多线程编程:从基础到实战

时间:2024-12-21 14:32:56浏览次数:11  
标签:std include lock 编程 C++ 线程 多线程

       随着多核处理器的普及,多线程编程成为现代 C++ 开发中的关键技能。C++11 引入了强大的线程库,使得多线程编程更安全、更高效。本文将带你深入了解 C++ 中的多线程编程,从基础概念到实际案例,逐步掌握如何用现代 C++ 编写高效的多线程程序。


一、多线程的基础概念

       多线程是一种并发编程技术,通过在单个程序中同时运行多个线程来提高效率。每个线程是独立的执行流,但共享同一进程的内存空间。

为什么需要多线程?
  1. 提升性能:利用多核 CPU 的计算能力并行执行任务。
  2. 响应式设计:在 GUI 或网络编程中保持界面的流畅性。
  3. 任务分解:将复杂的任务拆分为多个线程,提高代码的清晰度和执行效率。

二、C++11 中的多线程支持

       C++11 标准库引入了以下多线程相关的核心组件:

  1. std::thread:创建和管理线程。
  2. std::mutexstd::lock_guard:用于线程间的同步,防止数据竞争。
  3. std::condition_variable:实现线程间的协调与通信。
  4. std::futurestd::promise:提供线程间的结果传递与异步操作支持。

三、代码实例

1. 使用 std::thread 创建线程

示例:简单的多线程程序

#include <iostream>
#include <thread>

void printMessage(const std::string& message, int count) {
    for (int i = 0; i < count; ++i) {
        std::cout << message << " " << i << std::endl;
    }
}

int main() {
    std::thread t1(printMessage, "Thread 1", 5);
    std::thread t2(printMessage, "Thread 2", 5);

    t1.join(); // 等待 t1 完成
    t2.join(); // 等待 t2 完成

    std::cout << "All threads finished!" << std::endl;
    return 0;
}

输出示例:
       线程的输出可能交错:

Thread 1 0  
Thread 2 0  
Thread 1 1  
Thread 2 1  
...  
All threads finished!  
2. 使用 std::mutex 防止数据竞争

       当多个线程访问共享数据时,必须保护临界区,防止数据竞争。

示例:线程安全的计数器

#include <iostream>
#include <thread>
#include <mutex>

int counter = 0;  
std::mutex mtx;  

void increment(int iterations) {  
    for (int i = 0; i < iterations; ++i) {  
        std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁  
        ++counter;  
    }  
}  

int main() {  
    std::thread t1(increment, 1000);  
    std::thread t2(increment, 1000);  

    t1.join();  
    t2.join();  

    std::cout << "Final counter value: " << counter << std::endl;  
    return 0;  
}  

输出:

Final counter value: 2000  
3. 使用 std::condition_variable 实现线程间的通信

示例:生产者-消费者模型

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>

std::queue<int> dataQueue;
std::mutex mtx;
std::condition_variable cv;
bool done = false;

void producer() {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        dataQueue.push(i);
        std::cout << "Produced: " << i << std::endl;
        cv.notify_one();
    }
    {
        std::lock_guard<std::mutex> lock(mtx);
        done = true;
        cv.notify_all();
    }
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !dataQueue.empty() || done; });
        while (!dataQueue.empty()) {
            int value = dataQueue.front();
            dataQueue.pop();
            std::cout << "Consumed: " << value << std::endl;
        }
        if (done) break;
    }
}

int main() {
    std::thread prod(producer);
    std::thread cons(consumer);

    prod.join();
    cons.join();

    return 0;
}

输出:

Produced: 0  
Produced: 1  
...  
Consumed: 0  
Consumed: 1  
...  

四、C++ 多线程的注意事项

  1. 数据竞争:多个线程访问共享资源时,必须使用 std::mutex 保护。
  2. 死锁:避免多个线程同时尝试获取多个锁导致的死锁问题,建议使用 std::lock 或 RAII 工具如 std::lock_guard
  3. 性能损耗:线程的创建与上下文切换有一定开销,线程数应与硬件能力匹配。
  4. 使用线程池:对于大量小任务,建议使用线程池(如 std::async 或第三方库)。

五、总结

C++ 的多线程编程通过 std::thread 和相关工具提供了强大的并发能力。通过合理使用这些工具,开发者可以编写出高效、安全的多线程程序。在实际应用中,我们需要根据任务特点选择适当的同步和通信方式,同时警惕多线程编程中的常见陷阱。

标签:std,include,lock,编程,C++,线程,多线程
From: https://blog.csdn.net/byby0325_/article/details/144630842

相关文章

  • 【c++笔试强训】(第四十篇)
    目录主持⼈调度(⼆)(贪⼼+优先级队列)题目解析讲解算法原理编写代码游游的重组偶数(数学)题目解析讲解算法原理编写代码主持⼈调度(⼆)(贪⼼+优先级队列)题目解析1.题目链接:主持人调度(二)_牛客题霸_牛客网2.题目描述描述有n 个活动即将举办,每个活动都有开始时间与活动......
  • Linux 环境 c++ 实现单词数量统计
    g++的使用g++的安装升级#安装gccsudoapt-getinstallgcc#安装g++sudoapt-getinstallg++c++编译g++-o【生成目标文件名】【c++代码源文件】命令行传参使用命令行传参时使用此main函数argc表示传入参数个数argv用来访问参数,0为程序的名称,1到argc-1......
  • 【AI编程助手系列】国产AI编程工具四大金刚之 通义灵码
    系列文章目录......
  • 【Python GUI 编程】tkinter :Ttk 组合框 Combobox
    在本文中,将介绍如何创建一个tkinterCombobox组合框小部件,该小部件允许用户从一组值中选择一个值。Combobox组合框小部件是新增的Ttk主题小部件,是Entry文本框和Listbox列表框的组合。除了允许在一组值中选择一个值外,它还允许输入自定义值。创建组合框要创建组合框小部......
  • ssm毕设青少年编程课程教学评价源码+程序+论文
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容选题背景随着信息技术的迅猛发展,编程教育在青少年群体中的普及率日益提高,成为培养其创新思维和解决问题能力的重要途径。关于青少年编程课程的教学评价,现有研......
  • 【Python GUI 编程】tkinter:Ttk 选项卡 Notebook
    在本文中,将介绍如何使用TkinterNotebook小部件创建选项卡。Notebook是由TkinterTtk模块引入的强大小部件。允许开发者创建包含多个选项卡的界面,每个选项卡可以包含不同的内容。创建Notebook小部件,请使用如下构造函数:notebook=ttk.Notebook(master,**kw)添加选项卡......
  • C++ 中面向对象编程如何处理对象的状态存储与恢复?
    对象状态存储与恢复的基本概念在C++面向对象编程中,对象的状态是由其成员变量的值来确定的。对象状态存储是指将对象当前的成员变量值保存起来,而对象状态恢复则是指将之前保存的成员变量值重新赋值给对象,使对象回到之前的某个状态。通过序列化和反序列化实现状态存储与恢......
  • OneCode:开启高效编程新时代——企业定制出码手册
    一、概述   OneCode的DSM(领域特定建模)出码模块是一个强大的工具,它支持多种建模方式,并具有强大的模型转换与集成能力,能够提升开发效率和代码质量,同时方便团队协作与知识传承,还具备方便的仿真调试与部署功能以及DSM第三方语言转换特性。二、建模方式(一)CodeFirst......
  • JAVA基础教程-(一)JAVA面向对象编程
    教程目录JAVA基础教程JAVA面向对象编程(一)一、面向过程与面向对象1.1、何谓“面向对象”的编程思想?二、Java语言基本元素:类和对象2.1、Java类及类的成员三、对象的创建和使用3.1、对象的产生3.2、内存解析3.3、匿名对象JAVA基础教程J......
  • C++ 中面向对象编程如何处理对象的状态存储与恢复?
    1.为什么需要处理对象的状态存储与恢复?在一些应用场景中,需要保存对象的当前状态,以便在以后的某个时间点恢复到这个状态。例如,在游戏中可以保存玩家的进度,在软件的撤销/重做功能中需要保存对象在不同操作下的状态。2.在C++中如何实现对象的状态存储与恢复?手动实现:可以在......