C++多线程编程实践指南

一、多线程概述

多线程是一种利用CPU时间分片的并发编程方式,能够提高程序的执行效率。在C++中,多线程编程需要使用一系列的线程库来完成。除了常见的std::thread,还有boost::thread、pthread、Windows API等。

在使用多线程编程时,需要注意线程安全。多个线程同时访问同一个资源,可能会发生读写冲突,导致程序异常崩溃。因此,在编写多线程程序时,需要加锁来避免这类问题。

下面是一个简单的多线程程序示例:

#include <iostream>
#include <thread>

void PrintMsg(int id)
{
    std::cout << "Thread " << id << " is running\n";
}

int main()
{
    std::thread t1(PrintMsg, 1);
    std::thread t2(PrintMsg, 2);
    
    t1.join();
    t2.join();
    
    return 0;
}

代码解释:调用PrintMsg函数的两个线程t1和t2同时启动,分别输出”Thread 1 is running”和”Thread 2 is running”,最后再等待这两个线程的执行完毕。

二、线程同步

在多线程编程中,线程同步是一个非常重要的问题。线程同步指的是多个线程之间的协调和通信,以实现对共享资源的读写操作。

在C++中,线程同步的方式有多种,比如互斥锁(std::mutex)、条件变量(std::condition_variable)、原子变量(std::atomic)等。

下面是一个使用std::mutex同步的例子:

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

std::mutex g_lock;

void PrintMsg(int id)
{
    g_lock.lock();
    std::cout << "Thread " << id << " is running\n";
    g_lock.unlock();
}

int main()
{
    std::thread t1(PrintMsg, 1);
    std::thread t2(PrintMsg, 2);
    
    t1.join();
    t2.join();
    
    return 0;
}

代码解释:使用std::mutex来保证PrintMsg函数的输出不会被多个线程同时执行,从而保证线程安全。

三、线程池

线程池是一种常见的多线程编程模型,通过创建多个线程并分配工作任务的方式,来提高程序的执行效率。

C++11中也提供了线程池相关的库,比如std::async和std::future。

下面是一个使用std::async和std::future的例子:

#include <iostream>
#include <vector>
#include <future>

int Plus(int x, int y)
{
    return x + y;
}

int main()
{
    std::vector<std::future<int>> futures;
    for(int i = 0; i < 10; i++)
    {
        futures.push_back(std::async(Plus, i, i+1));
    }
    
    for(auto & f : futures)
    {
        std::cout << f.get() << std::endl;
    }
    
    return 0;
}

代码解释:将10个Plus函数的调用任务放入std::async函数中,在等待这些任务完成后,输出结果。

四、死锁问题

在多线程编程中,死锁是一个常见的问题。死锁指的是多个线程之间互相等待,导致程序无法继续执行。

死锁的解决方式主要有两种:1)避免嵌套锁;2)使用std::lock_guard来避免手动上锁和解锁。

下面是一个死锁示例:

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

std::mutex g_lock1, g_lock2;

void A()
{
    g_lock1.lock();
    std::cout << "A locked g_lock1\n";
    g_lock2.lock();
    std::cout << "A locked g_lock2\n";
    g_lock2.unlock();
    g_lock1.unlock();
}

void B()
{
    g_lock2.lock();
    std::cout << "B locked g_lock2\n";
    g_lock1.lock();
    std::cout << "B locked g_lock1\n";
    g_lock1.unlock();
    g_lock2.unlock();
}

int main()
{
    std::thread t1(A);
    std::thread t2(B);
    
    t1.join();
    t2.join();
    
    return 0;
}

代码解释:A函数先上锁g_lock1,然后又试图上锁g_lock2;B函数先上锁g_lock2,然后又试图上锁g_lock1,导致两个线程之间互相等待,产生死锁。

五、多线程性能优化

在多线程编程中,性能优化是一个非常重要的问题。性能优化可以从多个角度来进行优化,比如减少锁竞争、提高CPU利用率、使用局部变量等。

下面是一个使用std::lock_guard和局部变量的例子来减少锁竞争:

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

std::mutex g_lock;

void Add(std::vector<int> & v, int x)
{
    std::lock_guard<std::mutex> lock(g_lock);
    v.push_back(x);
}

void Worker()
{
    std::vector<int> v;
    for(int i = 0; i < 100000; i++)
    {
        Add(v, i);
    }
}

int main()
{
    std::vector<std::thread> threads;
    for(int i = 0; i < 10; i++)
    {
        threads.emplace_back(Worker);
    }
    
    for(auto & t : threads)
    {
        t.join();
    }
    
    return 0;
}

代码解释:每个线程都有一个局部变量v来存储数据,然后通过Add函数来向v中添加元素。由于每个线程有自己的局部变量,因此减少了锁竞争的发生。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/186340.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-11-27 05:45
下一篇 2024-11-27 05:45

相关推荐

  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • 运维Python和GO应用实践指南

    本文将从多个角度详细阐述运维Python和GO的实际应用,包括监控、管理、自动化、部署、持续集成等方面。 一、监控 运维中的监控是保证系统稳定性的重要手段。Python和GO都有强…

    编程 2025-04-29
  • Python应用程序的全面指南

    Python是一种功能强大而简单易学的编程语言,适用于多种应用场景。本篇文章将从多个方面介绍Python如何应用于开发应用程序。 一、Web应用程序 目前,基于Python的Web…

    编程 2025-04-29
  • Python wordcloud入门指南

    如何在Python中使用wordcloud库生成文字云? 一、安装和导入wordcloud库 在使用wordcloud前,需要保证库已经安装并导入: !pip install wo…

    编程 2025-04-29
  • Python小波分解入门指南

    本文将介绍Python小波分解的概念、基本原理和实现方法,帮助初学者掌握相关技能。 一、小波变换概述 小波分解是一种广泛应用于数字信号处理和图像处理的方法,可以将信号分解成多个具有…

    编程 2025-04-29
  • Python字符转列表指南

    Python是一个极为流行的脚本语言,在数据处理、数据分析、人工智能等领域广泛应用。在很多场景下需要将字符串转换为列表,以便于操作和处理,本篇文章将从多个方面对Python字符转列…

    编程 2025-04-29
  • Python初学者指南:第一个Python程序安装步骤

    在本篇指南中,我们将通过以下方式来详细讲解第一个Python程序安装步骤: Python的安装和环境配置 在命令行中编写和运行第一个Python程序 使用IDE编写和运行第一个Py…

    编程 2025-04-29
  • Python起笔落笔全能开发指南

    Python起笔落笔是指在编写Python代码时的编写习惯。一个好的起笔落笔习惯可以提高代码的可读性、可维护性和可扩展性,本文将从多个方面进行详细阐述。 一、变量命名 变量命名是起…

    编程 2025-04-29
  • Python多线程读取数据

    本文将详细介绍多线程读取数据在Python中的实现方法以及相关知识点。 一、线程和多线程 线程是操作系统调度的最小单位。单线程程序只有一个线程,按照程序从上到下的顺序逐行执行。而多…

    编程 2025-04-29
  • FusionMaps应用指南

    FusionMaps是一款基于JavaScript和Flash的交互式地图可视化工具。它提供了一种简单易用的方式,将复杂的数据可视化为地图。本文将从基础的配置开始讲解,到如何定制和…

    编程 2025-04-29

发表回复

登录后才能评论