[转]Linux线程同步之条件变量

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

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

条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。

条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步。

使用条件变量之前要先进行初始化。可以在单个语句中生成和初始化一个条件变量如:pthread_cond_t my_condition=PTHREAD_COND_INITIALIZER;(用于进程间线程的通信)。可以利用函数pthread_cond_init动态初始化。

条件变量分为两部分: 条件和变量. 条件本身是由互斥量保护的. 线程在改变条件状态前先要锁住互斥量. 它利用线程间共享的全局变量进行同步的一种机制。

相关的函数如下:

1 int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);     
2 int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
3 int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
4 int pthread_cond_destroy(pthread_cond_t *cond);  
5 int pthread_cond_signal(pthread_cond_t *cond);
6 int pthread_cond_broadcast(pthread_cond_t *cond);  //解除所有线程的阻塞
简要说明:     
      (1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER;属性置为NULL
      (2)等待条件成立.pthread_wait,pthread_timewait.wait()释放锁,并阻塞等待条件变量为真
      timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有一个线程wait)
      (3)激活条件变量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程)
      (4)清除条件变量:destroy;无线程等待,否则返回EBUSY
 
详细说明

1. 初始化:

    条件变量采用的数据类型是pthread_cond_t, 在使用之前必须要进行初始化, 这包括两种方式:

  • 静态: 可以把常量PTHREAD_COND_INITIALIZER给静态分配的条件变量.
  • 动态: pthread_cond_init函数, 是释放动态条件变量的内存空间之前, 要用pthread_cond_destroy对其进行清理.

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

成功则返回0, 出错则返回错误编号.

    当pthread_cond_init的attr参数为NULL时, 会创建一个默认属性的条件变量; 非默认情况以后讨论.

2. 等待条件:

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

成功则返回0, 出错则返回错误编号.

    这两个函数分别是阻塞等待和超时等待.

    等待条件函数等待条件变为真, 传递给pthread_cond_wait的互斥量对条件进行保护, 调用者把锁住的互斥量传递给函数. 函数把调用线程放到等待条件的线程列表上, 然后对互斥量解锁, 这两个操作是原子的. 这样便关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道, 这样线程就不会错过条件的任何变化.

    当pthread_cond_wait返回时, 互斥量再次被锁住.

3. 通知条件:

#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

成功则返回0, 出错则返回错误编号.

    这两个函数用于通知线程条件已经满足. 调用这两个函数, 也称向线程或条件发送信号. 必须注意, 一定要在改变条件状态以后再给线程发送信号.

示例程序
#include <stdio.h>
#include <pthread.h>
 pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread1(void *arg) 
{
	
pthread_cleanup_push(pthread_mutex_unlock, &mutex);
	
	    //提供函数回调保护
	    while (1) {
		
printf("thread1 is running\n");
		
pthread_mutex_lock(&mutex);
		
pthread_cond_wait(&cond, &mutex);
		
printf("thread1 applied the condition\n");
		
pthread_mutex_unlock(&mutex);
		
sleep(4);
	
}
	
pthread_cleanup_pop(0);

}


void *thread2(void *arg) 
{
	
while (1) {
		
printf("thread2 is running\n");
		
pthread_mutex_lock(&mutex);
		
pthread_cond_wait(&cond, &mutex);
		
printf("thread2 applied the condition\n");
		
pthread_mutex_unlock(&mutex);
		
sleep(1);
	
}

}

int main() 
{
	
pthread_t thid1, thid2;
	
printf("condition variable study!\n");
	
pthread_mutex_init(&mutex, NULL);
	
pthread_cond_init(&cond, NULL);
	
pthread_create(&thid1, NULL, (void *) thread1, NULL);
	
pthread_create(&thid2, NULL, (void *) thread2, NULL);
	
	do {
		
pthread_cond_signal(&cond);
	
} while (1);
	
sleep(20);
	
pthread_exit(0);
	
return 0;

}

 

条件变量与互斥锁、信号量的区别

       1.互斥锁必须总是由给它上锁的线程解锁,信号量的挂出即不必由执行过它的等待操作的同一进程执行。一个线程可以等待某个给定信号灯,而另一个线程可以挂出该信号灯。

       2.互斥锁要么锁住,要么被解开(二值状态,类型二值信号量)。

       3.由于信号量有一个与之关联的状态(它的计数值),信号量挂出操作总是被记住。然而当向一个条件变量发送信号时,如果没有线程等待在该条件变量上,那么该信号将丢失。

       4.互斥锁是为了上锁而设计的,条件变量是为了等待而设计的,信号灯即可用于上锁,也可用于等待,因而可能导致更多的开销和更高的复杂性。

参考:http://blog.csdn.net/dai_weitao/archive/2007/08/22/1754964.aspx


C++多线程并发(三)---线程同步条件变量 一、何为条件变量 在前一篇文章《C++多线程并发编程(二)—线程同步之互斥锁》中解释了线程同步的原理和实现,使用互斥锁解决数据竞争访问问题,算是线程同步的加锁原语,用于排他性的访问共享数据。我们在使用mutex时,一般都会期望加锁不要阻塞,总是能立刻拿到锁,然后尽快访问数据,用完之后尽快解锁,这样才能不影响并发性和性能。 如果需要等待某个条件的成立,我们就该使用条件变量(condition var... 阅读详情

相关推荐

海思Hi3516DV300实战:从yolov5模型训练到Sort跟踪算法的完整部署流程

本文详细介绍了在海思Hi3516DV300芯片上部署YOLOv5目标检测与Sort多目标跟踪算法的完整流程。内容涵盖从特定场景数据训练YOLOv5模型、模型格式换(PyTorch到ONNX再到Caffe),到利用海思NNIE引擎生成WK模型并进行端侧集成与优化的全链路实战经验,旨在解决嵌入式设备上实时人流量统计等实际应用挑战。

weixin_29034963的博客 314

Linux线程同步条件变量

与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。 条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。 条件的检测是在互斥锁的保护下进行的。如果一个条件为假,一个

wj_1986的专栏 728

【ArcGIS遇上Python】使用add-in向导开发ArcGIS插件(1):add-in工具介绍及安装

文章目录addin介绍addin下载addin安装 addin介绍 ArcGIS从10.0开始支持addin(ArcGIS软件中又叫作加载项)的方式进行插件制作。相对于以往9.x系列,addin的无论是从使用或者编写都更加方便快捷。通过开发语言,可以制作ArcGIS Desktop各个软件模块的插件。 Esri提供了Python加载项向导工具来实现Addin界面的搭建,可以到Esri官网去下载该工具Python加载项向导 。从介绍来看,该设计器要求的最低ArcGIS版本为10.1 ,如下图所示: add

智慧空间实验室 7146

线程同步总结

同步的概念 在数据库中同步的概念是指让两个数据库中或者多个数据库保持一致,而在编程中同步的概念时指协同步调,按先后次序运行 数据混乱原因 资源共享(独享资源则不会) 调度随机(意味着数据访问会出现竞争) 线程间缺乏必要的同步机制。 为了避免这种数据混乱,所以线程需要同步 “多个控制流,共同操作一个共享资源”的情况,都需要同步 线程同步的方法 1.互斥量mutex 函数 pthread_mut...

u010761477的博客 470

线程同步——优势、劣势

一、线程同步好处: 多个线程同时访问共享数据时,防止数据被损坏。 二、线程同步带来的问题: 1,实现比较繁琐,而且容易出错。 必须对多个线程可能同时访问的所有数据,用额外的代码包围起来,以获得和释放一个同步锁。这需要由程序员来保证没有遗漏,对多线程共享的数据的加锁工作。并且,在程序完成时,需要进行压力测试以保证多个线程并发时,结果如预期。 2,它会损害性能。 获取和释放一个锁是需要时间...

weixin_33736832的博客 392

linux线程条件变量

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

BuZiShuoquoto的博客 1026

】|【Linux线程同步-----条件变量

复习时看到这篇写的不错博客 解决了自己的疑惑!!! ----->>>linux 线程学习之条件变量

Lebron 257

Linux】多线程4——线程同步/条件变量

增加这个规则之后,下一个获取到锁的资源的线程就一定是在资源等待队列首部的线程,如果有十个线程,此时我们就能够让这十个线程按照某种次序进行临界资源的访问。例如,现在有两个线程访问一块临界区,一个线程往临界区写入数据,另一个线程从临界区读取数据,但。

2301_80224556的博客 1818

Linux线程 分离和同步与互斥 条件变量

线程分离是指线程在结束时,操作系统会自动回收其资源,而无需其他线程显式地等待它的结束或调用pthread_join函数。这种机制允许主线程不必关心子线程的状态,从而提高程序的并发性和可维护性。

yualian的博客 3102

[Linux]条件变量:实现线程同步(什么是条件变量、为什么需要条件变量,怎么使用条件变量(接口)、例子,代码演示(生产者消费者模型))

在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步。饥饿问题饥饿问题指的是某些线程由于某种原因无法获得它们所需要的资源或执行机会,导致它们长时间得不到处理,甚至永远得不到处理的现象。这种情况通常发生在多个线程竞争有限资源时,其中一些线程可能因为优先级过低、调度算法的不公平性、同步机制使用不当或其他原因而无法获得足够的执行时间。

2202_75305885的博客 9937

线程(四)线程同步——条件变量

本文主要介绍了线程同步与互斥的概念,并详细解释了条件变量线程同步中的应用。首先,文章通过一个产品发布的例子说明了线程同步的重要性,强调了线程之间的相互依赖和先后执行约束问题。接着,深入讲解了条件变量的定义、初始化、销毁以及等待操作和通知操作的实现方法。此外,还通过具体的代码示例展示了如何使用条件变量实现线程间的同步,包括使用条件变量进行线程同步的具体步骤和注意事项。最后,通过两个实例展示了条件变量在实际编程中的应用,帮助读者更好地理解和掌握线程同步与互斥的相关技术。

m0_52867657的博客 1333

Linux线程同步

Linux线程同步,一文带你搞懂线程同步

tan_run的博客 2084

Linux】< 条件变量等待>解决< 线程饥饿问题 >——【多线程同步问题】

一.概念&基本概念二. 为什么一定需要 ? 三.使用规范四.饥饿问题展示——"其他线程改变前,一直处于忙等待"1.基于【普通队列】的面临的2.基于【阻塞队列】的解决3.实现【阻塞队列】设计部分(图文详细解读)4.实现【阻塞队列】代码

YYDsis的博客 1282

Linux线程同步条件变量和信号量

本文系统介绍了线程同步机制中的条件变量和信号量。条件变量部分详细讲解了其工作原理及核心函数,包括pthread_cond_wait、pthread_cond_signal等,并附有示例代码演示线程同步实现。信号量部分区分了二进制信号量和计数信号量的应用场景,对比了有名信号量和无名信号量的特点及其API函数(如sem_init、sem_open等)。通过多个实际代码案例,展示了信号量在线程间和进程间同步的具体应用。全文最后总结了两种同步机制的选择原则和注意事项,为开发多线程/多进程程序提供了实用参考。

2302_77530416的博客 1687

Linux条件变量线程同步的利器

本文深入探讨Linux条件变量在多线程编程中的应用,详细解析其核心函数、工作原理及实战技巧。文章首先介绍条件变量的初始化与等待/唤醒机制,强调其与互斥锁的配合必要性。通过生产者-消费者模型展示条件变量的实际应用,并指出常见陷阱如虚假唤醒问题。最后提供性能优化建议和与信号量的对比分析,帮助开发者正确高效地使用这一线程同步利器。

软件科学-郝学胜 1144

linux线程同步条件变量和锁)

互斥锁、条件变量、自旋锁和读写锁在Linux线程同步中各有特点和适用场景。互斥锁是最常用的同步工具,适用于大多数场景。条件变量用于在特定条件满足时通知线程。自旋锁适用于对锁的等待时间较短且不希望线程上下文切换的场景。读写锁则在对共享资源进行读和写操作时提高效率。

千千道的博客 1712

Linux条件变量线程同步

本文介绍了线程同步中的条件变量机制。条件变量用于解决线程间的等待/通知问题,确保线程在满足特定条件前保持等待。

2301_80349538的博客 928

Linux】多线程线程同步条件变量

调用之前,必须先锁定互斥量。条件变量在内部会自动解锁互斥量并挂起线程,然后在条件满足后再重新锁定互斥量。使用后,需要在while循环中检查条件,以处理可能的虚假唤醒(假设线程被唤醒时条件并未真正满足)。可能会由于虚假唤醒而返回,即使条件尚未满足。因此,条件变量的等待通常放在while循环中,以确保条件的正确性。其他线程可以使用唤醒一个等待中的线程,或使用唤醒所有等待中的线程。在使用完条件变量和互斥量后,应该调用和来释放资源。

2301_76606232的博客 1566
上一篇: Proof of Concept
下一篇: 什么是真正的实时操作系统
chenziwen
博客等级 码龄19年 4粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值