C++详细分析线程间的同步通信

  #include

  #include //多线程的头文件

  #include //互斥锁的头文件

  #include //条件变量的头文件

  #include //C++ STL所有的容器都不是线程安全

  using namespace std;

  std::mutex mtx;//定义互斥锁,做线程间的互斥操作

  std::condition_variable cv;//定义条件变量,做线程间的同步通信操作

  //生产者生产一个物品,通知消费者消费一个;消费完了,消费者再通知生产者继续生产物品

  class Queue

  {

  public:

  void put(int val)//生产物品

  {

  unique_lock lck(mtx);//unique_ptr

  while (!que.empty())

  {

  //que不为空,生产者应该通知消费者去消费,消费者消费完了,生产者再继续生产

  //生产者线程进入#1等待状态,并且#2把mtx互斥锁释放掉

  cv.wait(lck);//传入一个互斥锁,当前线程挂起,处于等待状态,并且释放当前锁 lck.lock() lck.unlock

  }

  que.push(val);

  /*

  notify_one:通知唤醒另外的一个线程的

  notify_all:通知唤醒其它所有线程的

  通知其它所有的线程,我生产了一个物品,你们赶紧消费吧

  其它线程得到该通知,就会从等待状态 =》 到阻塞状态 =》 但是要获取互斥锁才能继续向下执行

  */

  cv.notify_all();

  cout << "生产者 生产:" << val << "号物品" << endl;

  }

  int get()//消费物品

  {

  lock_guard guard(mtx);//相当于scoped_ptr

  unique_lock lck(mtx);//相当于unique_ptr 更安全

  while (que.empty())

  {

  //消费者线程发现que是空的,通知生产者线程先生产物品

  //#1 挂起,进入等待状态 #2 把互斥锁mutex释放

  cv.wait(lck);

  }//如果其他线程执行notify了,当前线程就会从等待状态 =》到阻塞状态 =》但是要获取互斥锁才能继续向下执行

  int val = que.front();

  que.pop();

  cv.notify_all();//通知其它线程我消费完了,赶紧生产吧

  cout << "消费者 消费:" << val << "号物品" << endl;

  return val;

  }

  private:

  queue que;

  };

  //这里模拟生产者生产10个物品,消费者消费10个物品

  void producer(Queue* que)//生产者线程

  {

  for (int i = 1; i <= 10; ++i)

  {

  que->put(i);

  std::this_thread::sleep_for(std::chrono::milliseconds(100));//睡眠100毫秒

  }

  }

  void consumer(Queue* que)//消费者线程

  {

  for (int i = 1; i <= 10; ++i)

  {

  que->get();

  std::this_thread::sleep_for(std::chrono::milliseconds(100));//睡眠100毫秒

  }

  }

  int main()

  {

  Queue que; //两个线程共享的队列

  std::thread t1(producer, &que);//开启生产者线程

  std::thread t2(consumer, &que);//开启消费者线程

  //主线程等待两个子线程都执行完再结束。

  t1.join();

  t2.join();

  return 0;

  }