📜  c++ 并发 - C++ (1)

📅  最后修改于: 2023-12-03 15:14:00.132000             🧑  作者: Mango

C++ 并发

C++ 并发编程是指多个线程或进程同时执行任务,以提高程序的执行效率和性能。C++11 引入了一系列新的并发编程库和语言特性,使得 C++ 并发编程变得更加容易和高效。

并发编程基础知识
线程的创建和销毁

C++11 标准库中提供了 std::thread 类来创建线程,其构造函数接受一个函数指针或可调用对象作为参数,表示新线程的入口函数。例如:

#include <iostream>
#include <thread>

void func() {
    std::cout << "Hello, world!" << std::endl;
}

int main() {
    std::thread t(func);
    t.join(); // 等待线程结束
    return 0;
}

上面的代码创建一个新的线程 t,执行 func 函数,在主线程中等待 t 线程执行完毕后再退出。

当然也可以使用 detach() 方法让新线程与主线程分离,使得它们之间独立执行:

std::thread t(func);
t.detach(); // 与主线程分离

不过要注意,分离后的线程没有办法通过主线程来控制和等待,需要通过其他机制进行同步和通信。

线程的同步和通信

多个线程之间的同步和通信是并发编程中最重要的问题之一。C++11 提供了多种同步原语和通信机制,在高效处理并发问题时非常有用。这些机制包括:

  • std::mutexstd::lock_guard: 互斥锁和自动锁,保证同一时间只有一个线程可以访问共享资源。
  • std::unique_lockstd::condition_variable: 条件变量和独占锁,用于线程之间的等待和通知,也可以用于实现线程池和任务队列等高级同步机制。

例如,下面的代码演示了如何使用互斥锁来保护共享资源:

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

std::mutex mtx; // 全局互斥量

void func(int id) {
    std::lock_guard<std::mutex> lock(mtx); // 加锁
    std::cout << "Thread " << id << " is running" << std::endl;
}

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

上面的代码创建了两个线程,它们共享了一个 std::mutex 对象 mtx,保证了同一时间只有一个线程能够输出信息。

原子操作和内存模型

并发编程还需要考虑到多个线程同时访问同一块内存时可能出现的数据竞争问题。C++11 标准库中提供了原子操作和 Memory Order 模型来解决这个问题,它们可以保证多个线程对同一原子对象的操作是原子的(不可分割的)且具有可见性的。

例如,下面的代码演示了如何使用原子操作来保证并发计数的正确性:

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> counter(0); // 全局原子计数器

void func(int id) {
    for (int i = 0; i < 1000000; ++i) {
        ++counter; // 原子自增
    }
}

int main() {
    std::thread t1(func, 1), t2(func, 2);
    t1.join();
    t2.join();
    std::cout << "Counter = " << counter << std::endl;
    return 0;
}

上面的代码创建了两个线程,它们同时向同一计数器 counter 中累加数据,并保证了每次操作的原子性和可见性。

并发编程高级特性
C++11 并发库

C++11 标准库中包括了一系列新的并发编程库,使得 C++ 的并发编程变得更加简单和高效。这些库包括:

  • std::futurestd::promise: 异步操作和结果传递。
  • std::asyncstd::packaged_task: 异步函数和任务。
  • std::mutexstd::condition_variable: 同步和通信。
  • std::atomicstd::memory_order: 原子操作和内存模型。
  • std::threadstd::this_thread: 线程和线程操作。
  • std::chronostd::ratio: 时间和时间单位。
  • std::randomstd::uniform_int_distribution: 随机数和分布。

这些库大大简化了并发编程的复杂度,使得 C++ 的并发编程变得更容易上手和实现。

C++17 并发库

C++17 标准库进一步增强了 C++ 的并发编程能力,引入了一系列新的库和特性。这些库包括:

  • std::latchstd::barrier: 同步点和屏障。
  • std::semaphorestd::counting_semaphore: 信号量和计数信号量。
  • std::scoped_lockstd::shared_lock: 多锁和共享锁。
  • std::jthreadstd::stop_token: 轻量级线程和取消标记。
  • std::atomic_refstd::atomic_flag: 原子引用和原子标志。

这些新库和特性进一步提高了 C++ 的并发编程效率和可靠性,使得 C++ 成为一个优秀的并发编程语言。

总结

C++ 并发编程是指多个线程或进程同时执行任务,以提高程序的执行效率和性能。C++11 和 C++17 标准库中包括了一系列新的并发编程库和语言特性,大大简化了并发编程的复杂度,使得 C++ 的并发编程变得更加容易和高效。这些库包括线程的创建和销毁、线程的同步和通信、原子操作和内存模型等基础机制,以及异步操作、同步点和屏障、信号量和多锁等高级特性。C++ 的并发编程在各种应用场景中都有着广泛的用途,是一个非常重要和实用的编程技能。