std::condition_variable notify_one()与notify_all()的区别
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()的区别相关推荐
- C++ std::condition_variable::notify_one()与notify_all()
std::condition_variable的成员函数notify_one()与notify_all()是用来唤醒阻塞在wait()的线程.假如有多个线程调用condition_variable:: ...
- C++11条件变量:notify_one()与notify_all()的区别
notify_one()与notify_all()常用来唤醒阻塞的线程. notify_one():因为只唤醒等待队列中的第一个线程:不存在锁争用,所以能够立即获得锁.其余的线程不会被唤醒,需要等待再 ...
- C++ 多线程:条件变量 std::condition_variable
文章目录 描述 使用 描述 头文件<condition_variable> 定义 class condition_variable; 简介 之前我们也已经介绍过了C++多线程中互斥变量存在 ...
- 【转】C++11 并发指南五(std::condition_variable 详解)
http://www.cnblogs.com/haippy/p/3252041.html 前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三 ...
- C++11 并发指南五(std::condition_variable 详解)
前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...
- C++ std::condition_variable wait() wait_for() 区别
一.std::condition_variable 是条件变量. wait() 当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::uniqu ...
- C++11中std::condition_variable的使用
<condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...
- Multi-thread--C++11中std::condition_variable的使用
<condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...
- C++同步机制之条件变量(std::condition_variable)
文章目录 一.使用机制 1.1 涉及的主要概念 1.2 wait线程中的用法 1.3 notify线程中的用法 二.成员函数 2.1 唤醒函数 2.2 等待函数 三.为什么需要互斥锁 四.虚假唤醒 五 ...
- C++并发中的条件变量 std::condition_variable
简介 这个操作相当于操作系统中的Wait & Signal原语,程序中的线程根据实际情况,将自己阻塞或者唤醒其他阻塞的线程. 个人认为,条件变量的作用在于控制线程的阻塞和唤醒,这需要和锁进行相 ...
最新文章
- <学习日记>计算机网络第一章预习记录
- antisamy java_antisamy的使用方法
- [蓝桥杯][2013年第四届真题]大臣的旅费(树的直径)
- VC++ 使用attributes定义接口
- modbus协议手册_20种PLC元件编号和Modbus编号地址对应表
- [零基础学JAVA]Java SE应用部分-28.Java IO操作(02)
- C语言-07其它相关
- Golang开发环境配置
- java程序设计 论文_《JAVA程序设计》论文要求
- python彩票预测与分析_130期祥子大乐透预测奖号:后区大小分析
- Javascript 高级程序设计第三版理解
- bootcamp空间不足_Bootcamp安装WindowsXP补丁时C盘空间不足的解决措施
- java无头浏览器_java – 使用无头浏览器的Android Web Scraping
- cmd 环境下载文件的几种方法
- 每天学一个 Linux 命令(115):accton
- sql 取最近一周的周几_我最近的几周摘要
- iOS 开发中的日期格式
- ios设备备份,更新路径(mac os)
- Go语言学习之net包(The way to go)
- 涨知识!芯片是怎么做出来的,今天终于看懂了