本文简单介绍了一些 虚假唤醒(spurious wakeup) 相关的知识
(注: 本文假设读者对多线程开发有一定了解)

高层次的多线程编程中,条件变量是个常见的同步方法,跟传统仅使用互斥量的方法相比,条件变量可以减少锁的竞争.

拿 Pthread 举例,一个常见的条件变量的使用示例大概是这个样子的:

// flag for sync
bool g_signaled = false;
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;// wait method
void wait()
{ pthread_mutex_lock(&g_mutex);while (!g_signaled){      pthread_cond_wait(&g_cond, &g_mutex);}g_signaled = false;pthread_mutex_unlock(&g_mutex);
}// signal method
void signal()
{pthread_mutex_lock(&g_mutex);g_signaled = true;pthread_mutex_unlock(&g_mutex);  pthread_cond_signal(&g_cond);
}

代码中调用的 pthread_cond_wait 方法,作用在于可以让线程释放对应的互斥锁(g_mutex)并进入等待状态,然后在对应的条件变量(g_cond) signal 之后重新被唤醒并再次获取互斥锁.

上述示例代码中,我们在设置 g_signaled 之后调用了 pthread_cond_signal,正常来讲的话,之前调用 pthread_cond_wait 的线程会被唤醒,此时 g_signaled 应该一定为真,但是细心的朋友应该会发现,代码中我们却使用了一个循环来检查 g_signaled 的真值(并在发现 g_signaled 不为真时释放互斥锁然后重新进入了等待(通过重新调用 pthread_cond_wait)):

while (!g_signaled)
{      pthread_cond_wait(&g_cond, &g_mutex);
}

这么做的一个原因便是为了处理 虚假唤醒(spurious wakeup),所谓 虚假唤醒,指的是即便我们没有 signal 相关的条件变量(即没有调用 pthread_cond_signal),等待(调用了 pthread_cond_wait)的线程也可能被(虚假)唤醒,此时我们必须重新检查对应的标记值(以确认是否发生了(虚假)唤醒),又由于(虚假)唤醒可能会发生多次,所以我们最终需要使用循环来进行标记值检查.

虚假唤醒看上去很恼人,似乎我们应该在接口层消除这种现象(即让 pthread_cond_wait 不产生虚假唤醒),但有两个原因让虚假唤醒最终保留了下来:

1. 消除虚假唤醒非常困难

这里我们不对此做细节讲述,这里有些相关的讲解,有兴趣展开的朋友可以首先看看.

2. 即使消除了虚假唤醒,我们仍然需要循环检查标记值

这可能令人比较意外,问题在于除了虚假唤醒,还有一种称为 stolen wakeups 的现象也可能会影响标记值.

考虑下面的代码:

pthread_mutex_unlock(&g_mutex);
// gap here ...
pthread_cond_signal(&g_cond);

可以看到我们首先释放了互斥锁,接着 signal 了对应的条件变量,但是这两个操作之间是有"空隙"的,某一线程完全可以在这之间获取到互斥锁,改变标记值,然后再释放互斥锁,这导致标记值在 pthread_mutex_unlock 和 pthread_cond_signal 之间可能会发生变化,基于此,我们便仍然需要循环检查标记值(以防执行错误的逻辑).

编程小知识之 虚假唤醒(spurious wakeup)相关推荐

  1. 多线程并发编程需要注意虚假唤醒Spurious wakeup

    虚假唤醒  Spurious wakeup 如果等待线程在没有通知被调用的情况下唤醒,则称为Spurious wakeup. 解决方案就是: 使用while条件判断,更好的方案是避免使用wait这种低 ...

  2. [C++11 多线程同步] --- 条件变量的那些坑【条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)】

    1 条件变量的信号丢失 1.1 条件变量的信号丢失场景重现 拿生产者和消费者模型举例,看一段示例代码: #include <iostream> #include <vector> ...

  3. java suprious wakeup_多线程编程中条件变量和的spurious wakeup 虚假唤醒

    1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1)线程等待某 ...

  4. c语言代码游戏跳一跳,微信小程序《跳一跳》游戏里的编程小知识,你知道吗?...

    微信小程序<跳一跳>游戏里的编程小知识,你知道吗? 今日你跳了吗? 玩过的朋友都知道,跳一跳里的游戏操作非常简单,就用手指按住屏幕按住施放进行跳跃,整个游戏是个人都可以很轻松玩起来! 游戏 ...

  5. Linux网络编程小知识(字节序、IP格式、函数、子网掩码、DNS域名解析代码实现)

    参考:网络编程前的一些小知识–Linux笔记 作者:一只青木呀 发布时间: 2021-04-12 23:19:10 网址:https://blog.csdn.net/weixin_45309916/a ...

  6. 条件变量的虚假唤醒(spurious wakeups)问题

    引言 条件变量是我们常用的同步原语之一,它的正确使用方式一般如下图: 在wait端,我们必须把判断布尔条件和wait()放到while循环中,而不能用if语句,原因是可能会引起虚假唤醒. 那么,究竟什 ...

  7. 编程小知识 之 序列 rotate

    本文简述了 序列 rotate 的一些知识 基础 本篇文章中所说的 序列 rotate(旋转) 可能跟我们平常理解的 图像 rotate(旋转) 不太相同,所谓 序列 rotate,其实就是一种调整序 ...

  8. 编程小知识之 Dithering

    本文简单介绍了 Dithering(抖动) 的一些知识 图形后处理有一种操作称为 Dithering(抖动),所谓 Dithering,就是一种能够在较小色彩空间上"模拟出"较大色 ...

  9. python编程小知识_分享Python开发中要注意的十个小贴士

    大家请注意:这篇文中假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子:[2, 4, 6, ...

  10. 编程小知识之时间显示

    本文简述了编程中常见的时间显示问题 开发中总会在各种场景下遇到需要显示时间的情况,显示的格式要求又往往五花八门,正常的譬如: "2018年12月29日20点30分15秒", 简洁一 ...

最新文章

  1. MySQL面试题 | 附答案解析(六)
  2. .Net+SQL Server企业应用性能优化笔记3——SQL查询语句
  3. 如何搞垮一个技术大牛?
  4. 刘启成_编写并使用shell脚本
  5. DCMTK:读取DICOM图像,并使用设置创建PGM位图
  6. Cocos2d-x V3.2+Cocos Studio1.6 实现一个简单的uibutton点击功能
  7. P1341 无序字母对
  8. 在mysql中插入日期
  9. angular新建组件_精美Angular后台管理模板分享-前后端分离(含所有代码)
  10. nslookup java_使用JAVA实现nslookup命令
  11. 界面的创建(高仿QQ登入界面)
  12. ajax传参后台中文乱码
  13. python创建文件的方法_python创建文本文件的简单方法
  14. 神奇英语语法系列(二)——名词性从句
  15. 小米摄像头 rtmp_如何使用外部摄像头进行AmazonLive_wotobuy
  16. Apache JMeter 5.1.1 Win 10 环境变量配置
  17. 剑指offer55 二叉树的深度 捏软柿子
  18. 前端课程设计02-购物商城
  19. 测试用例的设计方法及案例
  20. 第十三届蓝桥杯国赛真题 PythonB组 复盘以及获奖感言(国一!!!)

热门文章

  1. html怎么导航栏中加边框,html – 使用CSS在导航栏中显示边框三角形
  2. 单独使用mybatis整合mysql案例
  3. xilinx低延时视频编解码方案
  4. Php—— 1.apache2.4.x+php7.x
  5. 配置微信公众号之公众号绑定小程序
  6. 通往诺贝尔奖之路:盘点10个著名的科学家族
  7. 我国街景地图向何处去
  8. 青果信息系统操作问题
  9. sass的安装、概念和使用
  10. 有道智云OCR图片识别文字+返回数据处理技巧(实现语言-按键精灵脚本请求识别+java服务端处理数据)...