多线程/多进程
thread
class thread; (C++11)
特点
- 线程在构造关联的线程对象时立即开始执行,存在 OS 调度延迟
- 从提供的作为构造函数参数的顶层函数开始,顶层函数的返回值将被忽略,若其以抛异常终止,则调用
std::terminate()
。 - 顶层函数可以通过
std::promise
或通过修改共享变量将其返回值或异常传递给调用方 thread
对象在默认构造,被移动,detach 或 join 后,不表示任何线程。在 detach 后执行的线程与任何thread
对象无关。thread::id
是thread
的唯一标识符,只有表示了线程,才会有 id。一旦线程结束,其值可为另一线程复用。
成员函数(部分)
operator=
: 移动 thread 对象joinable
: 检查对象是否活跃,若get_id() != thread::id()
,则返回true
,否则返回False
、native_handle
: 返回底层实现定义的线程句柄hardware_concurrency
(静态): 返回实现支持的并发线程数,若该值非良定义或不可计算,则返回 0join
: 阻塞当前线程直至*this
所标识的线程结束其执行,*this
不进行同步,多个线程在同一thread
上调用join
构成数据竞争detach
: 从thread
对象分离执行线程,一旦该线程退出,则释放任何分配的资源,调用detach
后,*this
不再占用任何线程
命名空间:this_thread
get_id()
: 获取线程 idyield()
: 放弃线程执行,回到就绪状态。即重新调度线程的执行,允许其他线程运行。此函数的准确行为依赖于实现,特别是取决于使用中的 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_one
或 notify_all
) 通知恢复
成员函数
wait()
: 被阻塞直至被 notified,或虚假唤醒发生- 线程在被
wait()
阻塞后,会自动调用unlock()
释放作为参数传入的锁,使得其他被锁阻塞的线程可以继续执行,当被唤醒后,会自动调用lock()
加锁。 - 参数
lock
为unique_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()
: 等待到某个时间点或被 notifiednotify_one()
: 解锁一个线程,如果有多个,则随机一个?notify_all()
: 解锁所有线程
condition_variable_any
condition_variable_any
类是 std::condition_variable
的泛化。它能在任何满足基本可锁定 (BasicLockable) 要求的锁上工作。
- 若锁是 std::unique_lock,则 std::condition_variable 可能提供更好的性能。
future
标准库提供了一些工具来获取异步任务(即在单独的线程中启动的函数)的返回值,并捕捉其所抛出的异常。这些值在共享状态中传递,其中异步任务可以写入其返回值或存储异常,而且可以由持有该引用该共享态的 std::future
或 std::shared_future
实例的线程检验、等待或是操作这个状态。