C++ 多线程编程概述
在当今计算机技术飞速发展的时代,多线程已经成为提高程序运行效率的重要手段。多线程程序能够在同一时间内执行多个任务,充分利用计算机的多核处理器,提高系统的并发性能。C++ 作为一门通用编程语言,对多线程编程提供了良好的支持。本文将介绍 C++ 多线程编程的基本概念、编程模型、同步机制以及一些实际应用案例。
一、C++ 多线程基本概念
1. 线程:线程是操作系统能够进行运算调度的最小单位,它被看做是一个进程执行任务的基本单位。一个进程可以包含多个线程,共享进程的内存空间和其他系统资源。
2. 并发与并行:并发是指多个任务在同一时间段内同时执行;并行是指多个任务在同一时刻同时执行。多线程编程主要关注的是并发,但在某些情况下,通过多线程实现并行也是可能的。
3. 线程调度:操作系统负责线程的调度,根据一定的策略分配CPU时间片给各个线程。线程的调度与进程的调度类似,但线程的调度更加轻量级。
4. 线程状态:线程在其生命周期中会经历多种状态,包括新建(NEW)、就绪(RUNNABLE)、运行(RUNNING)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)。
二、C++ 多线程编程模型
C++ 标准库提供了多种多线程编程模型,其中较为常用的是基于操作系统的线程(std::thread)和基于任务的线程(std::future、std::async)。下面分别介绍这两种模型。
1. 基于操作系统的线程
std::thread 类是 C++11 标准库中引入的,它封装了操作系统线程的创建、启动、同步和终止等操作。使用 std::thread 创建线程时,需要提供一个 Callable(可调用对象),如函数、 lambda 表达式等。
创建线程:
std::thread t(std::bind(function, args...));
启动线程:
t.start();
等待线程完成:
t.join();
获取线程返回值:
std::future<T> get_future(bool wait = true) { if (wait) { t.join(); } return t.get();}
2. 基于任务的线程
C++11 标准库还引入了 std::future、std::async 等功能,用于处理异步任务。基于任务的线程模型通过 std::future 和 std::async 实现,可以避免显式地操作线程,简化代码。
创建异步任务:
std::future<T> f = std::async(std::launch::deferred, function);
等待任务完成:
f.wait();
获取任务返回值:
T result = f.get();
三、C++ 多线程同步机制
在多线程环境下,为了防止多个线程同时访问共享资源导致数据不一致等问题,需要使用同步机制。C++ 标准库提供了多种同步工具,如下所示。
1. 互斥锁(std::mutex)
互斥锁用于保护共享资源,确保同一时刻只有一个线程可以访问共享资源。使用互斥锁时,需要使用 lock_guard 或其他类似对象锁定和解锁互斥锁。
std::mutex m;m.lock();// 访问共享资源m.unlock();
2. 读写锁(std::read_write_mutex)
读写锁分为读锁和写锁。在读锁保护期间,其他线程只能读取共享资源;在写锁保护期间,其他线程既不能读取也不能写入共享资源。使用读写锁可以提高并发性能,特别是在读操作远多于写操作的场景下。
std::read_write_mutex rwm;std::unique_lock<std::read_write_mutex> rlck(rwm::reader());// 读取共享资源
3. 条件变量(std::condition_variable)