千家信息网

Linux如何实现条件变量

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章给大家分享的是有关Linux如何实现条件变量的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量
千家信息网最后更新 2025年12月02日Linux如何实现条件变量

这篇文章给大家分享的是有关Linux如何实现条件变量的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。

当条件满足的时候,线程通常解锁并等待该条件发生变化,一旦另一个线程修改了环境变量,就会通知相应的环境变量唤醒一个或者多个被这个条件变量阻塞的线程。这些被唤醒的线程将重新上锁,并测试条件是否满足。一般来说条件变量被用于线程间的同步;当条件不满足的时候,允许其中的一个执行流挂起和等待。

简而言之,条件变量本身不是锁,但它也可以造成线程阻塞,通常与互斥锁配合使用,给多线程提供一个会合的场所。

条件变量的优点:

  • 相较于mutex而言,条件变量可以减少竞争。如果仅仅是mutex,那么,不管共享资源里有没数据,生产者及所有消费都全一窝蜂的去抢锁,会造成资源的浪费。

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

主要应用函数:

  • pthread_cond_init函数

  • pthread_cond_destroy函数

  • pthread_cond_wait函数

  • pthread_cond_timedwait函数

  • pthread_cond_signal函数

  • pthread_cond_broadcast函数

以上6 个函数的返回值都是:成功返回0, 失败直接返回错误号。

pthread_cond_t类型:用于定义条件变量,比如:pthread_cond_t cond;

##pthread_cond_init函数

函数原型:

int pthread_cond_init(pthread_cond_t restrict cond, const pthread_condattr_t restrict attr);

函数作用:初始化一个条件变量

参数说明:

  • cond:条件变量,调用时应传&cond给该函数

  • attr:条件变量属性,通常传NULL,表示使用默认属性

也可以使用静态初始化的方法,初始化条件变量:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

##pthread_cond_destroy函数

函数原型:

int pthread_cond_destroy(pthread_cond_t *cond);

函数作用:销毁一个条件变量

##pthread_cond_wait函数

函数原型:

int pthread_cond_wait(pthread_cond_t restrict cond, pthread_mutex_t restrict mutex);

函数作用:

阻塞等待一个条件变量。具体而言有以下三个作用:

  • 阻塞等待条件变量cond(参1)满足;

  • 释放已掌握的互斥锁mutex(解锁互斥量)相当于pthread_mutex_unlock(&mutex);

  • 当被唤醒,pthread_cond_wait函数返回时,解除阻塞并重新申请获取互斥锁

其中1、2.两步为一个原子操作。

##pthread_cond_timedwait函数

函数原型:

int pthread_cond_timedwait(pthread_cond_t restrict cond, pthread_mutex_t restrict mutex, const struct timespec *restrict abstime);

函数作用:限时等待一个条件变量

参数说明:

前两个比较好理解,重点说明第三个参数。

这里有个struct timespec结构体,可以在man sem_timedwait中查看。结构体原型如下:

struct timespec {  time_t tv_sec; / seconds / 秒   long tv_nsec; / nanosecondes/ 纳秒  }

struct timespec定义的形参abstime是个绝对时间。注意,是绝对时间,不是相对时间。什么是绝对时间?2018年10月1日10:10:00,这就是一个绝对时间。什么是相对时间?给洗衣机定时30分钟洗衣服,就是一个相对时间,也就是说从当时时间开始计算30分钟,诸如此类。

如:time(NULL)返回的就是绝对时间。而alarm(1)是相对时间,相对当前时间定时1秒钟。

adstime所相对的时间是相对于1970年1月1日00:00:00,也就是UNIX计时元年。

下面给出一个错误用法: struct timespec t = {1, 0}; pthread_cond_timedwait (&cond, &mutex, &t); 这种用法只能定时到 1970年1月1日 00:00:01秒,想必这个时间大家都还没出生。

正确用法: time_t cur = time(NULL); 获取当前时间。 struct timespec t; 定义timespec 结构体变量t t.tv_sec = cur+1; 定时1秒 pthread_cond_timedwait (&cond, &mutex, &t); 传参

##pthread_cond_signal函数

函数原型:

int pthread_cond_signal(pthread_cond_t *cond);

函数作用: 唤醒至少一个阻塞在条件变量上的线程

##pthread_cond_broadcast函数

函数原型:

int pthread_cond_broadcast(pthread_cond_t *cond);

函数作用: 唤醒全部阻塞在条件变量上的线程

##生产者消费者条件变量模型

不管是什么语言,只要提到线程同步,一个典型的案例就是生产者消费者模型。在Linux环境下,借助条件变量来实现这一模型,是比较常见的一种方法。

假定有两个线程,一个模拟生产者行为,一个模拟消费者行为。两个线程同时操作一个共享资源(一般称之为汇聚),生产向其中添加产品,消费者从中消费掉产品。

看如下示例,使用条件变量模拟生产者、消费者问题:

#include  #include #include #include typedef struct msg {    struct msg *next;     int num;}msg_t;msg_t *head = NULL;msg_t *mp = NULL;/* 静态初始化 一个条件变量 和 一个互斥量*/pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;void *th_producer(void *arg) {    while (1) {         mp = malloc(sizeof(msg_t));        mp->num = rand() % 1000;        //模拟生产一个产品         printf("--- produce: %d --------\n", mp->num);         pthread_mutex_lock(&mutex);        mp->next = head;         head = mp;        pthread_mutex_unlock(&mutex);        pthread_cond_signal(&has_product);      //唤醒线程去消费产品        sleep(rand() % 5);     }    return NULL; }void *th_consumer(void *arg) {    while (1) {         pthread_mutex_lock(&mutex);        while (head == NULL) {      //如果链表里没有产品,就没有抢锁的必要,一直阻塞等待             pthread_cond_wait(&has_product, &mutex);        }        mp = head;        head = mp->next;        //模拟消费掉一个产品         pthread_mutex_unlock(&mutex);        printf("========= consume: %d ======\n", mp->num);         free(mp);        mp = NULL;        sleep(rand() % 5);     }    return NULL; }int main(){    pthread_t pid, cid;    srand(time(NULL));     pthread_create(&pid, NULL, th_producer, NULL);    pthread_create(&cid, NULL, th_consumer, NULL);    pthread_join(pid, NULL);    pthread_join(cid, NULL);    return 0; }

运行结果:


感谢各位的阅读!关于"Linux如何实现条件变量"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

条件 变量 函数 线程 时间 消费 生产 消费者 阻塞 作用 原型 生产者 产品 就是 竞争 之间 两个 参数 模型 环境 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 从数据库中删除表 上海天朔网络技术有限公司 中金公司招聘软件开发岗 上海信息化软件开发销售 不能使用数据库主键自增 杭电中网络技术与应用 计算机与网络技术的优缺点 数据库2008哪几个版本 诺基亚登陆qq连接不到服务器 互联网科技实习生岗位职责 无法找到指定主机的服务器 达梦数据库创建只读用户 百度软件开发及云计算项目 我的职业理想软件开发 福建管理系统软件开发公司 雅安直销公司直销软件开发 asp net与数据库连接 腾讯计算机服务器在哪里 联想4g服务器多少钱 搭建企业内部存储服务器并分级 盐城网络营销软件开发售后服务 exce 查询重复数据库 上传文件保存到数据库 sql在软件开发中的作用 链接服务器会很费流量嘛 淄博设备软件开发服务 网络安全课堂怎么退出 网络安全有关英语 浙江智能化网络技术 数据库价格用什么类型
0