首页 > 编程语言 >多线程编程的基本概念,C++标准库中的多线程支持(std::thread,std::async),如何处理线程同步和并发问题。

多线程编程的基本概念,C++标准库中的多线程支持(std::thread,std::async),如何处理线程同步和并发问题。

时间:2024-07-04 14:27:18浏览次数:9  
标签:std 多线程 thread 线程 async include

多线程编程在现代计算机系统中非常重要,因为它能够使程序同时执行多个操作,提高计算效率。以下是多线程编程的基本概念及如何在C++标准库中使用std::threadstd::async进行多线程编程,同时处理线程同步和并发问题。

多线程编程的基本概念

  1. 线程(Thread):

    • 线程是一个轻量级的进程,是操作系统能够独立管理的基本单元。一个进程可以包含多个线程,这些线程共享进程的资源(如内存、文件句柄等)。
  2. 并发与并行(Concurrency vs. Parallelism):

    • 并发是指程序能够在同一时间处理多个任务。具体而言,虽然任务可能并不是同时运行的,但它们在程序中的执行顺序会交错进行。
    • 并行是指程序在同一时刻实际执行多个任务。并行通常需要多核处理器,多个任务真正同时进行。
  3. 线程安全(Thread Safety):

    • 当多个线程访问共享资源(如全局变量、文件等)时,如果没有适当的同步机制,就可能出现数据竞争(Data Race)和死锁(Deadlock)等问题。线程安全是指程序在多线程环境下运行时,能够正确地处理并发访问,不会出现错误。

C++ 标准库中的多线程支持

C++11引入了丰富的多线程支持,主要包括std::threadstd::async等工具。以下是它们的基本用法:

1. std::thread

std::thread提供了一个简单的接口来创建和管理线程。下面是一个基本的示例:

#include <iostream>
#include <thread>

// 线程执行的函数
void print_hello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    // 创建线程并启动
    std::thread t(print_hello);

    // 等待线程完成
    t.join();

    std::cout << "Hello from main!" << std::endl;

    return 0;
}

在这个示例中,std::thread t(print_hello); 创建并启动了一个新线程来执行print_hello函数。t.join(); 用于等待线程t完成。

2. std::async

std::async是一个高层次的接口,用于启动异步任务,并且它返回一个std::future对象,用于获取异步任务的结果。下面是一个基本的示例:

#include <iostream>
#include <future>

// 异步执行的函数
int compute_sum(int a, int b) {
    return a + b;
}

int main() {
    // 使用 std::async 启动异步任务
    std::future<int> result = std::async(std::launch::async, compute_sum, 10, 20);

    // 获取异步任务的结果
    int sum = result.get();
    std::cout << "Sum is: " << sum << std::endl;

    return 0;
}

在这个示例中,std::async启动了一个异步任务来计算两个整数的和,并返回一个std::future对象result。通过调用result.get(),可以获得异步任务的结果。

线程同步和并发问题的处理

为了保证线程安全,需要使用同步机制来管理对共享资源的访问。C++标准库提供了一些常用的同步原语:

  1. 互斥量(Mutex):

    • std::mutex:用于在多个线程之间保护共享资源,确保一次只有一个线程可以访问资源。
    • std::lock_guard:用于简化互斥量的使用,在一个作用域内自动锁定和解锁互斥量。
      #include <iostream>
      #include <thread>
      #include <mutex>
      
      std::mutex mtx; // 互斥量
      
      void print_number(int n) {
          std::lock_guard<std::mutex> lock(mtx);
          std::cout << "Number: " << n << std::endl;
      }
      
      int main() {
          std::thread t1(print_number, 1);
          std::thread t2(print_number, 2);
      
          t1.join();
          t2.join();
      
          return 0;
      }
      

 

2.条件变量(Condition Variable):

  • std::condition_variable:用于线程间的通信,使一个线程能够等待另一个线程的某个条件满足。
  • std::unique_lock:用于与条件变量一起使用,能够更灵活地控制互斥量的锁定和解锁。

 

#include <iostream>
#include <thread>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_message() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待条件满足
    std::cout << "Thread is running!" << std::endl;
}

int main() {
    std::thread t(print_message);

    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true; // 设置条件为 true
    }
    cv.notify_one(); // 通知等待的线程

    t.join();
    return 0;
}

3.原子操作(Atomic Operations):

  • 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: " << counter.load() << std::endl;
    
        return 0;
    }
    

    在这个示例中,std::atomic<int> 保证了对 counter 的操作是线程安全的,不需要使用互斥量来保护它。

    通过正确地使用这些工具和同步机制,可以有效地管理多线程程序中的并发问题,提高程序的性能和可靠性。

标签:std,多线程,thread,线程,async,include
From: https://blog.csdn.net/qq_44905692/article/details/140171324

相关文章

  • JAVA多线程快速入门
    什么是多线程概述线程线程是操作系统能够进行运算调度的最小单位它被包含在进程之中,是进程中的实际运作单位简单理解应用软件中互相独立,可以同时运行的功能进程进程是程序的基本执行实体/系统分配资源的基本单位作用充分利用cpu提......
  • Java多线程编程
    1.进程进程是指操作系统中正在运行的程序实例,它是系统资源分配的基本单位。每个进程都拥有独立的内存空间和系统资源,可以看作是程序的一次执行过程。2.线程线程是进程中的执行单元,也被称为轻量级进程(LightWeightProcess)。一个进程可以包含多个线程,这些线程共享进......
  • Winform SynchronizationContext多线程更新画面控件
    SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContextcontex......
  • Linux多进程和多线程(一)-进程的概念和创建
    进程进程的概念进程的特点如下进程和程序的区别LINUX进程管理getpid()getppid()进程的地址空间虚拟地址和物理地址进程状态管理进程相关命令pstoppstreekill进程的创建并发和并行fork()父子进程执行不同的任务创建多个进程进程的退出exit()和_exit()exit()函数......
  • 丝滑解决ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_
    基础环境:MacOSm1、python=3.9前情提要:在Anaconda终端运行代码的时候,显示报错:importError:/usr/lib/x86_64-linux-gnu/libstdc++.so.6:version`GLIBCXX_3.4.29'notfound1问题分析:根据提示是/usr/lib/x86_64-linux-gnu/路径下的libstdc++.so.6缺少版本GLIBCXX_3.4.29解......
  • ThreadLoop实践学习笔记
    背景在日常工作和学习源码过程中,经常可以看到ThreadLoop的运用,发现ThreadLoop作为一个基础工具,在具体项目中有不同而又十分相似的实现,虽然核心的机制万变不离其宗(IO多路复用),但面向的业务场景不同导致了不同的实践结果,目前见过有几种ThreadLoop的实践,本文做一个分析记录和知识点的......
  • 深入理解Qt多线程编程(QtConcurrent)
    多线程编程在现代软件开发中变得越来越重要,它能够提高应用程序的响应速度和处理性能。在Qt框架中,除了QThreadPool,QtConcurrent也是一个强大的工具,用于简化和管理多线程编程。目录概述接口详解QtConcurrent::runQtConcurrent::mapQtConcurrent::mappedQtConcurrent::filt......
  • Java_多线程:实现多线程
    Java中实现多线程的常用方式:继承Thread类实现Runnable接口实现Callable接口(JDK>=1.5)线程池方式创建实现Runnable接口与Callable接口的区别实现Runnable接口和Callable接口的方式基本相同,不过Callable接口里定义的方法返回值,可以声明抛出异常。Runnable和Callable与......
  • java多线程-锁的介绍
    多线程中常用锁一、锁的概念二、锁的类型2.1互斥锁(也称排它锁)2.1.1Synchronized和Lock2.1.2ReentrantLock(可重入锁)2.1.3公平锁2.1.4非公平锁2.1.5中断锁2.2共享锁2.3读写锁三、悲观锁和乐观锁3.1悲观锁3.2乐观锁3.3CAS算法四、锁竞争一、锁的概念在多......
  • 在多线程并发操作中处理大量文件时,以下是一些关键的底层原理和技术:
    在多线程并发操作中处理大量文件时,以下是一些关键的底层原理和技术:1.文件句柄管理每个线程需要独立地管理文件句柄,文件句柄是操作系统提供的用于标识和访问文件的资源。在Windows环境下,使用CreateFile函数可以打开文件并获得文件句柄。每个文件句柄具有其自己的上下文和状态,......