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();  // Wait for the thread to finish
   return 0;
}

输出

Hello Learner!

C++ 中的线程同步

C++ 中的线程同步是一种机制,它管理多个线程对共享资源的访问,以防止数据竞争、不一致和未定义的行为。它确保一次只有一个线程可以访问资源,或者特定操作按特定顺序执行,尤其是在多个线程并发执行时。

C++ 中线程同步的关键方法

以下是 C++ 中线程同步的一些关键方法:

互斥量(<mutex> 库)

互斥量(互斥)是一种锁定机制,它限制对共享资源的访问,以便一次只有一个线程可以访问它。如果一个线程锁定了互斥量,则尝试锁定相同互斥量的其他线程将被阻塞,直到互斥量被解锁。

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 或获取):减少信号量值。
  • 信号(V 或释放):增加信号量值。

C++ 中的异步执行

在 C++ 中,std::futurestd::promise 是用于异步编程的机制,它们有助于管理数据或在线程之间进行结果通信,允许一个线程提供结果(通过 std::promise)而另一个线程检索它(通过 std::future)。这些是 C++11 标准的一部分,可以在 <future> 头文件中找到。

异步编程的关键组件

  • std::future - 它表示异步操作的未来结果。一个线程可以在结果可用时从 future 中检索结果,如果结果未准备好,std::future::get() - 函数将阻塞直到计算出值。
  • std::promise - 它用于设置稍后可以通过 std::future 检索的值或异常。
  • std::async - 它用于异步启动任务。它返回一个 std::future,该 future 可用于在任务完成后获取任务的结果。
广告