个人知识库 个人知识库
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub

Agnes001

坚持是一件很伟大的事业
首页
关于
  • C语言
  • CPlusPlus
  • Linux
  • PHP
  • Nginx
  • MySQL
  • Redis
  • Docker
  • Kubernetes
  • SRS
阅读
常用工具
  • 分类
  • 标签
  • 归档
GitHub
  • C语言

  • CPlusPlus

    • 基础特性

    • vs2019设置
    • C++11特性

    • 并发编程

      • 并发编程
      • chrono
      • thread
      • mutex
      • condition_varible
        • condition_variable
          • std::condition_variable类
          • std::conditionvariableany类
      • future
      • atomic
    • 引用
    • 类和对象
    • 友元和运算符重载
    • 继承
    • 继承和多态
    • 模板
    • C++基础总结
    • 类型转换
    • 异常
    • 容器
    • 算法
    • C++程序设计
    • C++ Primer总结
    • 编程技巧
    • 标准库体系结构与内核分析
    • 设计模式
    • cmake配置C++工程
    • libcurl的使用总结
    • web开发框架--drogon
    • log4cplus使用
    • C++数据类型
    • 函数
    • 线程
    • 进程
    • 文件操作
    • 日常问题记录
    • Cpp案例程序
    • 多线程
    • 侯捷c++11新特性
    • 侯捷stl
  • Lua技术栈

  • edoyun

  • 内存管理

  • 数据结构

  • 网络编程

  • Linux

  • 池化技术

  • 操作系统

  • python

  • 编程技术
  • CPlusPlus
Agnes001
2022-07-05

condition_varible

# condition_variable

<condition_variable>头文件提供了条件变量的定义。其作为基本同步机制,允许被阻塞的线程在某些条件达成或超时时,解除阻塞继续执行。

namespace std
{
  enum class cv_status { timeout, no_timeout };

  class condition_variable;
  class condition_variable_any;
}

# std::condition_variable类

std::condition_variable 允许阻塞一个线程,直到条件达成。

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;   // 全局标志位

void printId(int id)
{
  std::unique_lock<std::mutex> lck(mtx);
  // 如果标志位不为true,则等待
  while(!ready)
  {
    // 线程被阻塞,直到标志位变为true
    cv.wait(lck);
  }
  std::cout << "thread: " << std::this_thread::get_id() << " id: " << id << "\n";
}

void go()
{
  std::unique_lock<std::mutex> lck(mtx);
  // 改变全局标志位
  ready = true;
  // 唤醒所有线程
  cv.notify_all();
}

int main()
{
  std::thread threads[10];

  for (int i = 0; i < 10; ++i)
  {
    threads[i] = std::thread(printId, i);
  }
  std::cout << "create done.\n" ;

  go();

  for (auto &t : threads)
  {
    t.join();
  }
  std::cout << "process done.\n" ;
  return 0;

//输出:
create done.
thread: 140496261539584 id: 0
thread: 140496253146880 id: 1
thread: 140496244754176 id: 2
thread: 140496227968768 id: 4
thread: 140496211183360 id: 6
thread: 140496194397952 id: 8
thread: 140496202790656 id: 7
thread: 140496186005248 id: 9
thread: 140496219576064 id: 5
thread: 140496236361472 id: 3
process done.

wait 操作 std::condition_variable 提供了两种 wait() 函数。

  • 无条件等待 void wait (unique_lock& lck); 当前线程调用 wait() 后将被阻塞(此时当前线程应该获得了锁(mutex),不妨设获得锁 lck),直到另外某个线程调用 notify_* 唤醒了当前线程。在线程被阻塞时(也就是调用 wait() 的时候),该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和 wait 函数被调用时相同。

  • 有条件等待 template void wait (unique_lock& lck, Predicate pred); 第二种情况设置了 Predicate,只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。因此第二种情况类似以下代码:

while (!pred()) { wait(lck); } 和 mutex 的 lock 类似,std::condition_variable 也提供了相应的两种(带 Predicate 和不带 Predicate) wait_for() 函数,与 std::condition_variable::wait() 类似,不过 wait_for 可以指定一个时间段,在当前线程收到通知或者指定的时间超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for 返回,剩下的处理步骤和 wait() 类似。还有 wait_util(),用法也类似。

notify 操作

  • std::condition_variable::notify_one() 唤醒某个等待(wait)线程。如果当前没有等待线程,则该函数什么也不做,如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified)。

  • std::condition_variable::notify_all() 唤醒所有的等待(wait)线程。如果当前没有等待线程,则该函数什么也不做。

非常好文:https://blog.csdn.net/KingOfMyHeart/article/details/118076229

# std::condition_variable_any类

与 std::condition_variable 类似,只不过 std::condition_variable_any 的 wait 函数可以接受任何 lockable 参数,而 std::condition_variable 只能接受 std::unique_lockstd::mutex 类型的参数,除此以外,和 std::condition_variable 几乎完全一样。

int main()
{
  std::queue<int> production;
  std::mutex mtx;
  std::condition_variable cv;
  bool ready = false;  // 是否有产品可供消费
  bool done = false;   // 生产结束

  std::thread producer(
    [&] () -> void {
      for (int i = 1; i < 10; ++i)
      {
        // 模拟实际生产过程
        std::this_thread ::sleep_for(std::chrono::milliseconds(10));
        std::cout << "producing " << i << std::endl;

        std::unique_lock<std::mutex> lock(mtx);
        production.push(i);

        // 有产品可以消费了
        ready = true;
        cv.notify_one();
      }
      // 生产结束了
      done = true;
    }
  );

  std::thread consumer(
    [&] () -> void {
      std::unique_lock<std::mutex> lock(mtx);
      // 如果生成没有结束或者队列中还有产品没有消费,则继续消费,否则结束消费
      while(!done || !production.empty())
      {
        // 防止误唤醒
        while(!ready)
        {
          cv.wait(lock);
        }

        while(!production.empty())
        {
          // 模拟消费过程
          std::cout << "consuming " << production.front() << std::endl;
          production.pop();
        }

        // 没有产品了
        ready = false;
      }
    }
  );

  producer.join();
  consumer.join();

  return 0;
}
编辑此页
mutex
future

← mutex future →

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式