生产者消费者模式在程序设计中出现频率非常高,经常会有线程间通过消息队列或其他共享变量进行交互的场景。而这时就会出现一个问题,消费者如何知道生产者已经生产了数据呢?有的程序会采取消费者循环判断消息队列大小是否为0,如果不为0则取出数据之类的方法。但是该种方法带来两个问题:

1. 生产者产出数据到消费者获得数据的延时较大。

2. CPU占用较高。

如果需要降低延时,则必然要提高轮询的频率,那么CPU占用就会升高。反之亦然,两者无法同时解决。

于是,唤醒等待机制就成为适合该种场景的解决方案。

该机制需要一个互斥对象以及条件变量共同完成,如下:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;

其中条件变量使用宏结构常量进行赋值。接下来进行互斥对象与条件变量的初始化:

pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);

生产者唤醒逻辑:

pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

消费者等待逻辑:

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

看到这里可能会有点疑问,为何除了条件变量还需要一个互斥对象呢?等待时为什么需要条件变量和互斥对象共同生效呢?

条件变量的操作也需要达到线程安全的要求,因此需要互斥对象来进行保证。避免两个线程同时操作条件变量引发问题。而通过查阅pthread_cond_wait()的相关资料可知,当程序运行到pthread_cond_wait()时,会将互斥对象锁释放,以便生产者能够顺利唤醒。而在消费者被成功唤醒,pthread_cond_wait()等待完成后,互斥对象会被重新上锁直到手动释放。

下方提供完整的DEMO以供参考:

/* test.cpp */

#include <pthread.h>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h> using namespace std; pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex; void *ThreadFunc(void *arg) { pthread_mutex_lock(&mutex);
/*此处等待唤醒*/
cout << "Thread sleeping..." << endl;
pthread_cond_wait(&cond, &mutex);
/*唤醒成功*/
cout << "Thread awakened!" << endl;
pthread_mutex_unlock(&mutex); return NULL;
} int main(void) { pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL); pthread_t tid;
pthread_create(&tid, NULL, ThreadFunc, NULL); /*等待5秒再唤醒,方便观察*/
usleep(); pthread_mutex_lock(&mutex);
/*唤醒*/
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex); return ;
}

附上操作命令:

g++ test.cpp -o test -pthread
./test

Linux线程唤醒与等待的更多相关文章

  1. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  2. “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. 第十七节:Runnable创建线程,Thread创建线程,唤醒线程和计数器多线程,线程同步与等待

    Runnable创建线程 public class RunnableDemo implements Runnable{ @Override public void run(){ int i = 1; ...

  4. Linux 线程管理

    解析1 LINUX环境下多线程编程肯定会遇到需要条件变量的情况,此时必然要使用pthread_cond_wait()函数.但这个函数的执行过程比较难于理解. pthread_cond_wait()的工 ...

  5. linux线程

    线程:轻量级进程,在资源.数据方面不需要进行复制 不间断地跟踪指令执行的路径被称为执行路线 进程的结构:task_struck:地址空间 线程:轻量级的进程 在同一个进程中创建的线程,在共享进程的地址 ...

  6. Linux线程学习(一)

    一.Linux进程与线程概述 进程与线程 为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同一个变量.所以,程序中的所有线程都可 ...

  7. Linux 线程与进程,以及通信

    http://blog.chinaunix.net/uid-25324849-id-3110075.html 部分转自:http://blog.chinaunix.net/uid-20620288-i ...

  8. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  9. (转)linux进程 linux线程 信息查看 ps top pstree

    原文:https://blog.csdn.net/xiaoliuliu2050/article/details/81912202 https://blog.csdn.net/u011734144/ar ...

随机推荐

  1. (转)2019年给Java编程初学者的建议(附学习大纲)

    本文链接:https://blog.csdn.net/javajlb/article/details/85920904 1. 引言这是一篇初学者干货,请耐心看完,希望对你有帮助 作为初学者的你,命中了 ...

  2. nessus安装

    1.安装注册 (1)从https://www.tenable.com/products/nessus/select-your-operating-system上下载对应操作系统版本的nessus,结果 ...

  3. pak文件的打包和解包

    pak格式的文件 一般游戏有资源 游戏素材会打包放进去 比如游戏语音 游戏多加点语音  多加一些贴图资源 外部文件实现的 素材--->pak文件--->用的时候从文件中取出来 文件的打包 ...

  4. 100天搞定机器学习|day45-53 推荐一本豆瓣评分9.3的书:《Python数据科学手册》

    <Python数据科学手册>共五章,每章介绍一到两个Python数据科学中的重点工具包.首先从IPython和Jupyter开始,它们提供了数据科学家需要的计算环境:第2章讲解能提供nda ...

  5. 操作微信-itchat库的安装

    基于pyCharm开发环境,在CMD控制台输入:pip install itchat      等待安装...... Microsoft Windows [版本 6.1.7601]版权所有 (c) 2 ...

  6. Java基础之多态和泛型浅析

    Java基础之多态和泛型浅析 一.前言: 楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结 二.什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面 ...

  7. Leetcode之深度优先搜索(DFS)专题-1020. 飞地的数量(Number of Enclaves)

    Leetcode之深度优先搜索(DFS)专题-1020. 飞地的数量(Number of Enclaves) 深度优先搜索的解题详细介绍,点击 给出一个二维数组 A,每个单元格为 0(代表海)或 1( ...

  8. Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)

    Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...

  9. mysql count(*)与count(1)的区别

    count() 对行数进行计算,包括NULL: count(column) 计算特定的列的值的行数,不包括NULL: count(1)这个用法和count()的结果是一样的. http://blog. ...

  10. ResourceManager基本职能和内部架构

    YARN也采用了Master/Slave结构,其中,Master实现为ResourceManager,负责整个集群资源的管理与调度:Slave实现为NodeManager,负责单个节点的资源管理与任务 ...