c++多线程详解

  • atomic
    • atomic
      • atomic_bool
      • atomic_int
      • atomic_long
    • atomic_flag
  • thread
    • thread类创建线程,接受函数和函数参数作为thread类参数
  • mutex
    • mutex类,互斥量
      • mutex 最基本的Mutex类
      • recursive_mutex 递归Mutex类,允许同一线程对互斥量多次上锁(递归上锁),来获得互斥量对象的多层所有权。释放互斥量时需要调用与该锁层次深度相同次数的unlock()
      • time_mutex 定时Mutex类
        • try_lock_for() 接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得互斥量的锁,如果超时返回false
        • try_lock_until() 接受一个时间点作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时返回false
      • recursive_timed_mutex 定时递归Mutex类
    • Lock类
      • lock_guard 与Mutex RAII相关,方便线程对互斥量上锁
        • 模板类,template class lock_guard;
        • lock_guard对象通常用于管理某个锁对象
        • 在某个lock_guard对象的声明周期内,它所管理的锁对象会一直保持上锁状态。而lock_guard的生命周期结束之后,它所管理的锁对象会被解锁。
        • 不负责管理Mutex对象的生命周期,只是简化了Mutex对象的上锁和解锁操作,方便线程对互斥量上锁。
        • 构造函数
          • explicit lock_guard(mutex_type& m); locking初始化,在构造时对m进行上锁
          • lock_guard(mutex_type& m, adopt_lock_t tag); adopting初始化,在Mutex对象m已经被当前线程锁住后调用
          • lock_guard(const lock_guard&) = delete; 拷贝构造和移动构造均被禁用
      • unique_lock 与Mutex RAII相关,方便线程对互斥量上锁,但提供了更好的上锁和解锁控制
        • 以独占所有权的方式管理mutex对象的上锁和解锁操作
        • 构造函数
          • unique_lock() noexcept; 默认构造函数,不管理任何Mutex对象
          • explicit unique_lock(mutex_type& m); locking初始化,管理Mutex对象m,并尝试调用m.lock()对Mutex对象进行上锁,如果此时另外某个unique_lock对象已经管理了该Mutex对象m,则当前线程将会被阻塞
          • unique_lock(mutex_type& m, try_to_lock_t tag); try_locking初始化,尝试上锁不成功时不会阻塞当前线程
          • unique_lock(mutex_type&m, defer_lock_t tag) noexcept; deferred初始化,初始化时并不锁住Mutex对象,m应该是一个没有当前线程锁住的Mutex对象
          • unique_lock(mutex_type&m, adopt_lock_t tag); adopting初始化,m应该是一个已经被当前线程锁住的Mutex对象。
          • template<class Rep, class Period> unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); locking一段时间,试图调用m.try_lock_for来锁住Mutex对象一段时间(rel_time)
          • template<class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); locking到某个时间点(abs_time)之前
          • unique_lock(const unique_lock&) = delete; 拷贝构造被禁用
          • unique_lock(unique_lock&& x); 移动构造被禁用
    • 其他类型
      • once_flag
      • adopt_lock_t
      • defer_lock_t
      • try_to_lock_t
    • 函数
      • lock() 可以同时对多个互斥量上锁
        • 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用unlock之前,该线程一直拥有该锁
        • 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住
        • 如果当前互斥量被当前调用线程锁住,则会发生死锁(deadlock)
      • try_lock() 尝试同时对多个互斥量上锁,如果互斥量被其他线程占有,则当前线程也不会被阻塞
        • 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用unlock之前,该线程一直拥有该锁
        • 如果当前互斥量被其他线程锁住,则当前的调用线程返回false,并不会被阻塞掉
        • 如果当前互斥量被当前调用线程锁住,则会发生死锁(deadlock)
      • unlock() 解锁
  • condition_variable 条件变量。当condition_variable对象的某个wait函数被调用的时候,它使用unique_lock(通过mutex)来锁住当前线程。当前线程会一直阻塞,直到另外一个线程在相同的condition_variable对象上调用了notification函数来唤醒当前线程
    • condition_variable类 通常使用unique_lock来等待
      • 构造函数
        • condition_variable();
        • condition_variable(const codition_variable&) = delete; 拷贝构造函数被禁用
      • condition_variable::wait()函数
        • void wait(unique_lock<mutex>& lck); 当前线程调用wait()后将阻塞,直到另外某个线程调用notify_*唤醒当前线程。在线程被阻塞时,该函数会自动调用lck.unlock()释放锁,使得其他阻塞在锁竞争上的线程得以继续执行。另外,一旦当前线程获得通知,wait()函数也是自动调用lck.lock(),使得lck的状态和wait函数被调用时相同
        • template<class Predicate> void wait(unique_lock<mutex>& lck, Predicate pred); 只有当pred条件为false时调用wait()都会阻塞当前线程,并且在收到其他线程的通知后只有当pred为true时才会被解除阻塞。类似于`while(!pred()) wait(lck);
      • condition_variable::wait_for()函数 可以指定一个时间段
      • condition_variable::wait_until()函数 可以指定一个时间点
      • condition_variable::notify_one()介绍 唤醒某个等待线程。如果当前没有等待线程,则该函数什么也不做。如果同时存在多个等待线程,则唤醒某个线程是不确定的
      • condition_variable::notify_all()介绍 唤醒所有等待线程。
    • condition_variable_any 通常使用另外的lockable类型来等待。wait函数可以接受任何lockable参数
    • cv_status 枚举类型
      • cv_status::no_timeout wait_for或者wait_until没有超时,即在规定的时间段内线程收到了通知
      • cv_status::timeout wait_for或者wait_until超时
    • notify_all_at_thread_exit
  • future
    • Provider类
      • promise
        • promise对象可以保存某一类型T的值,该值可被future对象读取(可能在另外一个线程中),因此promise也提供了一种线程同步的手段
        • 在promise对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保存一个类型为T的值
        • 可以通过get_future来获取与该promise对象相关联的fuure对象,调用该函数之后,两个对象共享相同的共享状态(shared state)
        • promise对象是异步Provider,它可以在某一时刻设置共享状态的值
        • future对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为ready,然后才能获取共享状态的值。
        • 构造函数
          • promise(); 默认构造函数,初始化一个空的共享状态
          • template <class Alloc> promise(allocator_arg_t aa, const Alloc& alloc); 带自定义内存分配器的构造函数,与默认构造函数类似,但是使用自定义分配器来分配共享状态
          • promise(const promise&) = delete; 拷贝构造函数被禁用
          • promise(promise&& x) noexcept; 移动构造函数
        • promise的operator=没有拷贝语义,即普通的赋值操作被禁用。operator=只有move语义,所以promise对象是禁止拷贝的
        • 成员函数
          • promise::get_future() 该函数返回一个与promise共享状态相关联的future。返回的future对象可以访问由promise对象设置在共享状态上的值或者某个异常对象。只能从promise共享状态获取一个future对象。在调用该函数之后,promise对象通常会在某个时间点准备好(设置一个值或者一个异常对象),如果不设置值或者异常,promise对象在析构时会自动地设置一个future_error异常(broken_promise)来设置其自身的准备状态
          • promise::set_value() 设置共享状态的值, 此后promise的共享标志变为ready
          • promise::set_exception() 为promise设置异常,此后promise的共享状态标志变为ready
      • package_task
    • Futures类
      • future
      • shared_future
    • 其他类型
      • future_error
      • future_errc
      • future_status
      • launch
    • async()函数
    • future_category()函数

发表评论