条件变量和原子型式

一.std::condition_variable类
必须与std::unique_lock配合使用
std::condition_variable_any类
更加通用的条件变量,可以与任意型式的互斥锁配合使用,相比前者使用时会有额外的开销
多线程通信同步原语
阻塞一个或多个线程至收到来自其他线程的通知,超时或发生虚假唤醒
两者具有同样的成员函数,且在等待条件变量前都必须要获得相应的锁
二.成员函数notify_one():通知一个等待线程
原型:void motify_one() noexcept;
成员函数notify_all():通知全部等待线程
原型:void motify_one() noexcept;
成员函数wait():阻塞当前线程至被唤醒
原型:template<typename Lock> void wait( Lock & lock );
原型:template<typename Lock, typename Predicate> void wait( Lock & lock, Predicate p );
三.成员函数wait_for():阻塞至被唤醒或超过指定时长
原型: template<typename Lock, typename Rep, typename _Period> cv_status wait_for( Lock& lock, const chrono::duration<Rep, Period>& rtime );
原型:template<typename Lock, typename Rep, typename Period, typename Predicate> bool wait_for( Lock& lock, const chrono::duration<Rep, Period>& rtime, Predicate p );
成员函数wait_until():阻塞至被唤醒或到达指定时点
原型:template<typename Lock, typename Clock, typename Duration> cv_status wait_until( Lock & lock,  const chrono::time_point<Clock, Duration>& atime);
原型:template<typename Lock, typename Clock, typename Duration, typename Predicate> bool wait_until( Lock& lock, const chrono::time_point<Clock, Duration>& atime, Predicate p );
四.#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex  x;
std::condition_variable  cond;
bool  ready = false;
bool  IsReady()  {  return ready;  }
void  Run( int no )
{
  std::unique_lock<std::mutex>  locker( x );
  while( !ready )		//  若标志位非true,阻塞当前线程
    cond.wait( locker );	//  解锁并睡眠,被唤醒后重新加锁
  //  以上两行代码等价于cond.wait( locker, &IsReady );
  //  第二个参数为谓词,亦可使用函子实现
  std::cout << "thread " << no << '\n';
}
int  main()
{
  std::thread  threads[8];
  for( int i = 0; i < 8; ++i )
    threads[i] = std::thread( Run, i );
  std::cout << "8 threads ready...\n";
  {
    std::unique_lock<std::mutex>  locker( x );    //  互斥加锁
    ready = true;		//  设置全局标志位为true
    cond.notify_all();	//  唤醒所有线程
  }    //  离开作用域,自动解锁;可将此复合语句块实现为函数
  //  基于区间的循环结构,对属于threads数组的所有元素t,执行循环体
  for( auto & t: threads )
    t.join();
  return 0;
}
原子型式
一.
使用方法
使用atomic模板定义原子对象
使用预定义标准原子型式:atomic_bool、atomic_char、atomic_int、atomic_uint、atomic_long、atomic_wchar_t等等
意义:轻量级,支持单变量上的原子操作
二.

三.#include <atomic>
#include <iostream>
#include <thread>
int  n = 0;
std::atomic<int>  a( 0 );
void  AddAtomically( int m )  {  while( m-- )  a.fetch_add( 1 );  }
void  Add( int m )  {  while( m-- )  ++n;  }
int  main()
{
  std::thread  ts1[8], ts2[8];
  for( auto & t: ts1 )  t = std::move( std::thread( AddAtomically, 1000000 ) );
  for( auto & t: ts2 )  t = std::move( std::thread( Add, 1000000 ) );
  for( auto & t: ts1 )  t.join();
  for( auto & t: ts2 )  t.join();
  //  输出结果:a值固定,而n值多次运行结果可能不同
  std::cout << "a = " << a << std::endl;
  std::cout << "n = " << n << std::endl;
  return 0;
}

你可能感兴趣的:(条件变量和原子型式)