当前位置: 首页 > news >正文

Linux-条件变量

文章目录

  • 条件变量
      • 概述
      • 条件变量的优缺点
      • 条件变量相关函数
        • pthread_cond_init函数
        • pthread_cond_destroy函数
        • pthread_cond_wait函数
        • pthread_cond_signal函数
      • 测试生产者和消费者模型

条件变量

概述

与互斥锁不同,条件变量是用来等待而不是用来上锁的,条件变量本身不是锁

条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。

条件变量的两个动作:

  • 条件不满, 阻塞线程
  • 当条件满足, 通知阻塞的线程开始工作

条件变量的类型: pthread_cond_t。

条件变量的优缺点

相较于mutex而言,条件变量可以减少竞争。
如直接使用mutex,除了生产者、消费者之间要竞争互斥量以外,消费者之间也需要竞争互斥量,但如果汇聚(链表)中没有数据,消费者之间竞争互斥锁是无意义的。
有了条件变量机制以后,只有生产者完成生产,才会引起消费者之间的竞争。提高了程序效率。

条件变量相关函数

pthread_cond_init函数

#include <pthread.h>
​
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
功能:初始化一个条件变量
参数:cond:指向要初始化的条件变量指针。attr:条件变量属性,通常为默认值,传NULL即可也可以使用静态初始化的方法,初始化条件变量:pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
返回值:成功:0失败:非0错误号
pthread_cond_destroy函数
#include <pthread.h>
​
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁一个条件变量
参数:cond:指向要初始化的条件变量指针
返回值:成功:0失败:非0错误号
pthread_cond_wait函数
#include <pthread.h>
​
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
功能:阻塞等待一个条件变量a) 阻塞等待条件变量cond(参1)满足b) 释放已掌握的互斥锁(解锁互斥量)相当于pthread_mutex_unlock(&mutex);a) b) 两步为一个原子操作。c) 当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁pthread_mutex_lock(&mutex);
​
参数:cond:指向要初始化的条件变量指针mutex:互斥锁
​
返回值:成功:0失败:非0错误号
​
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct.*restrict abstime);
功能:限时等待一个条件变量
​
参数:cond:指向要初始化的条件变量指针mutex:互斥锁abstime:绝对时间
​
返回值:成功:0失败:非0错误号

abstime补充说明:

struct timespec {time_t tv_sec;      /* seconds */ // 秒long   tv_nsec; /* nanosecondes*/ // 纳秒
}
​
time_t cur = time(NULL);        //获取当前时间。
struct timespec t;              //定义timespec 结构体变量t
t.tv_sec = cur + 1;             // 定时1秒
pthread_cond_timedwait(&cond, &t);
pthread_cond_signal函数
#include <pthread.h>
​
int pthread_cond_signal(pthread_cond_t *cond);
功能:唤醒至少一个阻塞在条件变量上的线程
参数:cond:指向要初始化的条件变量指针
返回值:成功:0失败:非0错误号
​
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:唤醒全部阻塞在条件变量上的线程
参数:cond:指向要初始化的条件变量指针
返回值:成功:0失败:非0错误号

测试生产者和消费者模型

#include <stdio.h>
#include <string.h> 
#include <stdlib.h> #include <unistd.h>
#include <pthread.h>pthread_cond_t cond;
pthread_mutex_t mutex;typedef struct _node_t
{int data;struct _node_t *next;
}node_t;node_t *head = NULL;void *producer(void *arg)
{node_t *new = NULL;while(1){pthread_mutex_lock(&mutex);new = malloc(sizeof(node_t));if(NULL == new){printf("malloc failed\n");pthread_mutex_unlock(&mutex);break;}memset(new, 0, sizeof(node_t));new->data = random() % 100 + 1;new->next = head;head = new;printf("-------生产者生产了产品 %d\n", new->data);pthread_mutex_unlock(&mutex);pthread_cond_signal(&cond);sleep(random() % 3 + 1);}pthread_exit(NULL);
}void *customer(void *arg)
{node_t *tmp = NULL;while(1){pthread_mutex_lock(&mutex);if(NULL == head){//阻塞在条件变量pthread_cond_wait(&cond, &mutex);}//删除链表第一个节点tmp = head;head = head->next;printf("消费者消费产品 %d\n", tmp->data);free(tmp);pthread_mutex_unlock(&mutex);sleep(random() % 3 + 1);}pthread_exit(NULL);
}
int test01()
{int ret = -1;pthread_t tid1 = -1;pthread_t tid2 = -1;srandom(time(NULL));ret = pthread_mutex_init(&mutex, NULL);if(0 != ret){printf("pthread_mutex_init failed\n");goto err0;}ret = pthread_cond_init(&cond, NULL);if(0 != ret){printf("pthread_cond_init failed\n");goto err0;}//生产者线程ret = pthread_create(&tid1, NULL, producer, NULL);if(0 != ret){printf("pthread_create failed\n");goto err0;}//消费者线程ret = pthread_create(&tid1, NULL, customer, NULL);if(0 != ret){printf("pthread_create failed\n");goto err0;}pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
err0:return 1;
}

文章转载自:

http://DJaK8SDN.ycpnm.cn
http://4XRC6MbY.ycpnm.cn
http://fLyelXwR.ycpnm.cn
http://ILojUi51.ycpnm.cn
http://Rd6bHw1h.ycpnm.cn
http://CfDSR2u7.ycpnm.cn
http://qfguimjW.ycpnm.cn
http://1GyjycCY.ycpnm.cn
http://zhy1HZOa.ycpnm.cn
http://curXGmAO.ycpnm.cn
http://EUepln5c.ycpnm.cn
http://NUsOjpiM.ycpnm.cn
http://T6Ej6GPy.ycpnm.cn
http://mtUHrIbZ.ycpnm.cn
http://ZHxhy5VH.ycpnm.cn
http://0zXoU1zL.ycpnm.cn
http://LRT1FMvq.ycpnm.cn
http://DfJaha3h.ycpnm.cn
http://UgJ3gWhn.ycpnm.cn
http://a2mcFJWu.ycpnm.cn
http://DMdM8VYq.ycpnm.cn
http://JqrPDqvL.ycpnm.cn
http://IgDniQYF.ycpnm.cn
http://ETTd4TpW.ycpnm.cn
http://C4sotEs2.ycpnm.cn
http://z4qdvAhy.ycpnm.cn
http://Bng2w419.ycpnm.cn
http://3Wu46aGB.ycpnm.cn
http://V3Fhpf24.ycpnm.cn
http://e7X2EW4l.ycpnm.cn
http://www.dtcms.com/a/372854.html

相关文章:

  • 6.python——字符串
  • 懒汉式——LazyMan(任务队列应用)
  • Nginx 实战系列(四)—— Nginx反向代理与负载均衡实战指南
  • Nginx 反向代理 + Tomcat 集群:负载均衡配置步骤与核心原理
  • 【Linux】匿名管道和进程池
  • PWA:打造媲美 Native Apps 的 Web 应用体验
  • # 小程序 Web 登录流程完整解析
  • 2025中国AI HR市场深度洞察:趋势、厂商与未来展望
  • 并发编程的守护者:信号量与日志策略模式解析
  • Flink Task线程处理模型:Mailbox
  • ActiveMQ classic ,artemis ,artemis console ,nms clients,cms client详解
  • 【论文阅读】Far3D: Expanding the Horizon for Surround-view 3D Object Detection
  • Three.js使用outlinePass描边后,描边颜色和背景叠加变淡
  • GPT系列--类GPT2源码剖析
  • 反编译分析C#闭包
  • DTO与POJO:核心差异与最佳实践
  • #C语言——刷题攻略:牛客编程入门训练(九):攻克 分支控制(三)、循环控制(一),轻松拿捏!
  • Android 中 自定义 RecyclerView 控件限制显示高度
  • Codesy中的UDP发送信息
  • Hadoop进程:深入理解分布式计算引擎的核心机制
  • SQL Server死锁排查实战指南
  • 自学嵌入式第三十八天:数据库
  • 【开题答辩全过程】以 基于springboot的酒店管理系统设计与实现为例,包含答辩的问题和答案
  • SpringBoot控制层接收参数处理、Logback日志入门和使用
  • Python快速入门专业版(十三):Python变量进阶:全局变量与局部变量(含global关键字用法)
  • 深度学习(二):神经元与神经网络
  • 如何在不同 iOS 设备上测试和上架 uni-app 应用 实战全流程解析
  • iOS 开发全流程实战 基于 uni-app 的 iOS 应用开发、打包、测试与上架流程详解
  • [论文阅读] 人工智能 + 软件工程 | 大模型破局跨平台测试!LLMRR让iOS/安卓/鸿蒙脚本无缝迁移
  • 汇编基础1