notify_one()notify_all()常用来唤醒阻塞的线程,线程被唤醒后立即尝试获得锁。

notify_one()因为只唤醒一个线程,不存在锁争用,所以能够立即获得锁。其余的线程不会被唤醒,等待再次调用notify_one()或者notify_all()

notify_all()会唤醒所有阻塞的线程,存在锁争用,只有一个线程能够获得锁。那其余未获取锁的线程接着会怎么样?会阻塞?还是继续尝试获得锁?答案是会阻塞,等待操作系统在互斥锁的状态发生改变时唤醒线程。当持有锁的线程释放锁时,操作系统会唤醒这些阻塞的线程,而这些线程会继续尝试获得锁。


看下面的例子:

// condition_variable example
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variablestd::mutex mtx;
std::condition_variable cv;
bool ready = false;void print_id(int id) {std::unique_lock<std::mutex> lck(mtx);while (!ready) cv.wait(lck);// ...std::cout << "thread " << id << '\n';
}void go() {std::unique_lock<std::mutex> lck(mtx);ready = true;// cv.notify_all(); // cv.notify.one();
}int main()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i < 10; ++i)threads[i] = std::thread(print_id, i);std::cout << "10 threads ready to race...\n";go();                       // go!for (auto& th : threads) th.join();return 0;
}

go()函数为如下时:

void go() {std::unique_lock<std::mutex> lck(mtx);ready = true;cv.notify_all(); // cv.notify.one();
}

运行结果为:

10 threads ready to race...
thread 2
thread 0
thread 9
thread 4
thread 6
thread 8
thread 7
thread 5
thread 3
thread 1

cv.notify_all()被调用后,所有子线程都被唤醒,然后尝试获得锁,其中的一个线程获得锁后继续执行后面的代码,而未获得锁的线程再次进入阻塞状态,等待操作系统在当前获得锁的线程释放锁之后唤醒它们。当获得锁的线程的线程函数执行完毕释放互斥锁后,刚刚的那些处于阻塞的线程会都被唤醒,其中的一个会获得互斥锁,而其余的再次进行阻塞状态。之后循环这个过程,知道所有的子线程最终都能够获得锁而正常退出。


go()函数为如下时:

void go() {std::unique_lock<std::mutex> lck(mtx);ready = true;// cv.notify_all(); cv.notify.one();
}

运行结果为:

10 threads ready to race...
thread 0

cv.notify_one()被调用后,只会唤醒一个线程,其余的阻塞线程由于没有被通知,所以一致会保持在阻塞状态。即使那个被唤醒的线程在线程函数执行完毕后互斥锁已被释放,其余的阻塞线程依旧不会有任何反应。


因此,线程阻塞在条件变量时,等待notify_one()或者notify_all()来唤醒。线程被唤醒后,会尝试获得锁,如果未获得锁,会重新进入阻塞状态。

注意区分线程处理阻塞状态时,是由于等待条件阻塞或是尝试获得锁而阻塞。
如果是因为等待条件变量阻塞,只能由notify_one()或者notify_all()来唤醒;
如果是为尝试获得锁而阻塞,只能由操作系统在锁的状态发生变化时唤醒;

std::condition_variable notify_one()与notify_all()的区别相关推荐

  1. C++ std::condition_variable::notify_one()与notify_all()

    std::condition_variable的成员函数notify_one()与notify_all()是用来唤醒阻塞在wait()的线程.假如有多个线程调用condition_variable:: ...

  2. C++11条件变量:notify_one()与notify_all()的区别

    notify_one()与notify_all()常用来唤醒阻塞的线程. notify_one():因为只唤醒等待队列中的第一个线程:不存在锁争用,所以能够立即获得锁.其余的线程不会被唤醒,需要等待再 ...

  3. C++ 多线程:条件变量 std::condition_variable

    文章目录 描述 使用 描述 头文件<condition_variable> 定义 class condition_variable; 简介 之前我们也已经介绍过了C++多线程中互斥变量存在 ...

  4. 【转】C++11 并发指南五(std::condition_variable 详解)

    http://www.cnblogs.com/haippy/p/3252041.html 前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三 ...

  5. C++11 并发指南五(std::condition_variable 详解)

    前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...

  6. C++ std::condition_variable wait() wait_for() 区别

    一.std::condition_variable 是条件变量. wait() 当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::uniqu ...

  7. C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  8. Multi-thread--C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  9. C++同步机制之条件变量(std::condition_variable)

    文章目录 一.使用机制 1.1 涉及的主要概念 1.2 wait线程中的用法 1.3 notify线程中的用法 二.成员函数 2.1 唤醒函数 2.2 等待函数 三.为什么需要互斥锁 四.虚假唤醒 五 ...

  10. C++并发中的条件变量 std::condition_variable

    简介 这个操作相当于操作系统中的Wait & Signal原语,程序中的线程根据实际情况,将自己阻塞或者唤醒其他阻塞的线程. 个人认为,条件变量的作用在于控制线程的阻塞和唤醒,这需要和锁进行相 ...

最新文章

  1. <学习日记>计算机网络第一章预习记录
  2. antisamy java_antisamy的使用方法
  3. [蓝桥杯][2013年第四届真题]大臣的旅费(树的直径)
  4. VC++ 使用attributes定义接口
  5. modbus协议手册_20种PLC元件编号和Modbus编号地址对应表
  6. [零基础学JAVA]Java SE应用部分-28.Java IO操作(02)
  7. C语言-07其它相关
  8. Golang开发环境配置
  9. java程序设计 论文_《JAVA程序设计》论文要求
  10. python彩票预测与分析_130期祥子大乐透预测奖号:后区大小分析
  11. Javascript 高级程序设计第三版理解
  12. bootcamp空间不足_Bootcamp安装WindowsXP补丁时C盘空间不足的解决措施
  13. java无头浏览器_java – 使用无头浏览器的Android Web Scraping
  14. cmd 环境下载文件的几种方法
  15. 每天学一个 Linux 命令(115):accton
  16. sql 取最近一周的周几_我最近的几周摘要
  17. iOS 开发中的日期格式
  18. ios设备备份,更新路径(mac os)
  19. Go语言学习之net包(The way to go)
  20. 涨知识!芯片是怎么做出来的,今天终于看懂了

热门文章

  1. mysql中权限的小知识
  2. python去除\ufeff、\xa0、\u3000
  3. MySQL并行复制的深入浅出
  4. Discuz!客户端api开发(一)
  5. Android 文件存放路径
  6. Linux locale
  7. 14.使用 CSS 显示 XML
  8. 第010讲 通配符选择器 父子选择器
  9. faster rcnn论文_论文导读-从Faster-RCNN/Mask RCNN/Cascade-RCNN到HTC
  10. Go Node.js 生成的exe公布成windows服务