C++ 并发
并发是指系统允许同时管理多个任务或进程,并允许它们在不等待彼此完成的情况下继续运行的能力。并发系统中的任务可以重叠执行,这最终有助于提高效率和资源利用率,尤其是在操作系统、数据库和 Web 服务器等环境中。
C++ 中的并发
在 C++ 中,并发可帮助开发者创建能够执行多个操作的应用程序,并有助于提高其效率和响应能力。并发可以通过多种方式实现,例如通过多线程、异步编程或分布式系统。
并发与并行
并发是指以重叠方式管理不同任务或处理器的能力,这意味着任务可以在不同的时间启动、执行和完成。这意味着任务可能不会同时运行,但它们的执行可以在时间上重叠,从而高效利用可用资源。
然而,并行是并发的一个子类别,其中任务实际上是在不同的处理器或核心上并发执行,以提高性能。
并发处理结构和任务管理,而并行则侧重于同时执行以加快计算速度。
线程
线程是进程中最小的执行单位,它允许多个任务独立且并发地运行。<thread>库用于创建和管理线程。线程并行运行并共享相同的内存空间。
示例
这是一个 C++ 中线程的简单示例 -
#include <iostream> #include <thread> void hello() { std::cout << "Hello Learner!" << std::endl; } int main() { std::thread t(hello); t.join(); // 等待线程完成 return 0; }
输出
Hello Learner!
C++ 中的线程同步
C++ 中的线程同步是一种管理多个线程对共享资源访问的机制,旨在防止数据争用、不一致和未定义行为。它确保同一时刻只有一个线程可以访问资源,或者特定操作按特定顺序执行,尤其是在多个线程并发执行的情况下。
C++ 中线程同步的关键方法
以下是 C++ 中线程同步的一些关键方法 -
互斥锁(<mutex> 库)
互斥锁(mutual exclusion)是一种锁定机制,它限制对共享资源的访问,使得同一时刻只有一个线程可以访问。如果一个线程锁定了互斥锁,则尝试锁定同一互斥锁的其他线程将被阻塞,直到互斥锁解锁为止。
std::lock_guard 和 std::unique_lock
std::lock_guard 是一个基本的自动锁管理器,它在创建互斥锁时锁定它,并在互斥锁超出范围时解锁它。
std::unique_lock 更加灵活,允许手动解锁和重新锁定。
条件变量(<condition_variable> 库)
它使线程能够等待,直到满足某些条件,从而促进线程之间的通信。
std::condition_variable 通常与 std::unique_lock<std::mutex> 一起使用。并提供 wait()、notify_one() 和 notify_all() 函数,用于根据特定条件阻塞和恢复线程。
原子变量(<atomic> 库)
原子操作是另一种无需使用互斥锁即可确保线程安全的方法。
原子变量保证任何读取-修改-写入操作都不会受到其他线程的干扰,这对于整数或布尔值等简单数据类型非常有用。
原子操作包括 fetch_add、load、store 和 compare_exchange。
信号量
信号量是一种同步原语,用于管理并发系统(例如多线程或多进程环境)中对共享资源的访问。信号量本质上是一个控制资源访问的整数值。它主要进行两项操作:
- 等待(P 或 acquire):减少信号量值。
- 信号(V 或 release):增加信号量值。
C++ 中的异步执行
在 C++ 中,std::future 和 std::promise 是用于异步编程的机制,用于管理数据或实现线程间通信,允许一个线程提供结果(通过 std::promise),另一个线程检索结果(通过 std::future)。它们是 C++11 标准的一部分,位于 <future> 中。标头。
异步编程的关键组件
- std::future − 它表示异步操作的 Future 结果。一旦 Future 可用,线程就可以从中获取结果;如果结果尚未准备好,std::future::get() − 函数将阻塞,直到计算出结果为止。
- std::promise − 它用于设置一个值或异常,稍后可以通过 std::future 获取。
- std::async − 它用于异步启动任务。它返回一个 std::future,可用于在任务完成后获取结果。