跳到主要内容

多线程/多进程

thread

class thread; (C++11)

特点

  • 线程在构造关联的线程对象时立即开始执行,存在 OS 调度延迟
  • 从提供的作为构造函数参数的顶层函数开始,顶层函数的返回值将被忽略,若其以抛异常终止,则调用std::terminate()
  • 顶层函数可以通过std::promise或通过修改共享变量将其返回值或异常传递给调用方
  • thread对象在默认构造,被移动,detach 或 join 后,不表示任何线程。在 detach 后执行的线程与任何thread对象无关。
  • thread::idthread的唯一标识符,只有表示了线程,才会有 id。一旦线程结束,其值可为另一线程复用。

成员函数(部分)

  • operator=: 移动 thread 对象
  • joinable: 检查对象是否活跃,若get_id() != thread::id(),则返回true,否则返回False
  • native_handle: 返回底层实现定义的线程句柄
  • hardware_concurrency(静态): 返回实现支持的并发线程数,若该值非良定义或不可计算,则返回 0
  • join: 阻塞当前线程直至*this所标识的线程结束其执行,*this不进行同步,多个线程在同一thread上调用join构成数据竞争
  • detach: 从thread对象分离执行线程,一旦该线程退出,则释放任何分配的资源,调用detach后,*this不再占用任何线程

命名空间:this_thread

  • get_id(): 获取线程 id
  • yield(): 放弃线程执行,回到就绪状态。即重新调度线程的执行,允许其他线程运行。此函数的准确行为依赖于实现,特别是取决于使用中的 OS 调度器机制和系统状态。例如,先进先出实时调度器(Linux 的 SCHED_FIFO)将悬挂当前线程并将它放到准备运行的同优先级线程的队列尾(而若无其他线程在同优先级,则 yield 无效果)。
  • sleep_for(): 阻塞当前线程至少指定(秒)
  • sleep_until(): 阻塞当前线程直到(时间),时间需满足std::chrono::is_clock_v<Clock>True

atomic 原子操作

template< class T >
struct atomic;

这些组建为细粒度的原子操作提供,允许无锁并发编程。涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的。原子对象不具有数据竞争。

条件变量

条件变量允许一定量的线程等待(可以定时)另一线程的提醒,然后再继续。条件变量始终关联到一个互斥。

condition_variable


condition_variable条件变量与 std::unique_lock 关联,可以阻塞 (wait, wait_for, wait_until) 调用的线程,直到使用 (notify_onenotify_all) 通知恢复

成员函数

  • wait(): 被阻塞直至被 notified,或虚假唤醒发生
    • 线程在被wait()阻塞后,会自动调用unlock()释放作为参数传入的锁,使得其他被锁阻塞的线程可以继续执行,当被唤醒后,会自动调用lock()加锁。
    • 参数lockunique_lock类型
    • 参数pred需返回bool类型,只有当pred == true时,且被 notified 时,才解除阻塞。等价于:
      while (!pred()) { // 在进入 pred() 前,要确保已经得到 lock
      wait(lock);
      }
  • wait_for(): 等待超时或被 notified
    • 返回值:无pred时,若超过指定的关联时限为std::cv_status::timeout,否则为std::cv_status::no_timeout;有pred时,若经过时限后,pred仍为false,则为false,否则为true
  • wait_until(): 等待到某个时间点或被 notified
  • notify_one(): 解锁一个线程,如果有多个,则随机一个?
  • notify_all(): 解锁所有线程

condition_variable_any


condition_variable_any 类是 std::condition_variable 的泛化。它能在任何满足基本可锁定 (BasicLockable) 要求的锁上工作。

  • 若锁是 std::unique_lock,则 std::condition_variable 可能提供更好的性能。

future

标准库提供了一些工具来获取异步任务(即在单独的线程中启动的函数)的返回值,并捕捉其所抛出的异常。这些值在共享状态中传递,其中异步任务可以写入其返回值或存储异常,而且可以由持有该引用该共享态的 std::futurestd::shared_future 实例的线程检验、等待或是操作这个状态。