C语言之pthread_cond_t信号变化探究总结(八十)

2023-10-07 23:10

本文主要是介绍C语言之pthread_cond_t信号变化探究总结(八十),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的: 理解pthread_cond_wait与pthread_cond_timedwait用法区别

函数区别
pthread_cond_wait与pthread_cond_signal函数成对出现,如果没有pthread_cond_signal给它发信号,它死等,等到天荒地老…
pthread_cond_timedwait自己设置超时时间,一旦超过设定时间,自动执行pthread_cond_timedwait函数后边的代码。如果pthread_cond_signal在pthread_cond_timedwait 设置超时时间之前给它发信号,它会收到信号,提前结束等待。
pthread_cond_signal一次只能唤醒一个等待中的线程
pthread_cond_broadcast可以唤醒全部等待中的线程
pthread_mutex_t Linux中用于互斥锁的结构体类型。互斥锁用于保护临界区,确保同时只有一个线程可以访问共享资源。
pthread_cond_t在Linux中,pthread_cond_t是用于线程间同步的条件变量。条件变量用于在线程之间传递信号,帮助线程进行等待和唤醒操作。条件变量通常与互斥锁(pthread_mutex_t)一起使用。当某个线程需要等待某个条件满足时,它会调用pthread_cond_wait函数将自己阻塞,并释放占有的互斥锁。当另一个线程满足了条件并调用了pthread_cond_signal或pthread_cond_broadcast函数发送信号时,等待的线程会被唤醒并重新获取互斥锁,从而继续执行。

2.代码示例

v1.0 pthread_cond_signal和pthread_cond_wait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;pthread_mutex_lock(&mutex);//1.如果不调用pthread_cond_signal(&cond)函数发信号,永远死等.pthread_cond_wait(&cond, &mutex);cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.sleep(1);pthread_cond_signal(&cond);//仅可以唤醒一个线程sleep(2);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));thread.join();return 0;
}

v2.0 pthread_cond_signal和pthread_cond_timedwait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;struct timeval now;struct timespec outtime;gettimeofday(&now, NULL);outtime.tv_sec = now.tv_sec + 10;//如果没有等到信号,则超过10s后自动处理.outtime.tv_nsec = now.tv_usec * 1000;pthread_mutex_lock(&mutex);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));//2.可以设置超时时间,一旦超过设定时间,自动执行pthread_cond_timedwait函数后边的代码,它不受pthread_cond_signal的影响.pthread_cond_timedwait(&cond, &mutex, &outtime);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});sleep(1);pthread_cond_signal(&cond);//仅可以唤醒一个线程sleep(2);thread.join();return 0;
}

v3.0 pthread_cond_broadcast和pthread_cond_wait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;pthread_mutex_lock(&mutex);//1.如果不调用pthread_cond_signal(&cond)函数发信号,永远死等.pthread_cond_wait(&cond, &mutex);cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.sleep(1);pthread_cond_broadcast(&cond);//可以唤醒全部线程sleep(2);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));thread.join();return 0;
}

v4.0 pthread_cond_broadcast和pthread_cond_timedwait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;struct timeval now;struct timespec outtime;gettimeofday(&now, NULL);outtime.tv_sec = now.tv_sec + 10;//如果没有等到信号,则超过10s后自动处理.outtime.tv_nsec = now.tv_usec * 1000;pthread_mutex_lock(&mutex);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));//2.可以设置超时时间,一旦超过设定时间,自动执行pthread_cond_timedwait函数后边的代码,它不受pthread_cond_signal的影响.pthread_cond_timedwait(&cond, &mutex, &outtime);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});sleep(1);pthread_cond_broadcast(&cond);//可以唤醒全部线程sleep(2);thread.join();return 0;
}

v5.0 pthread_cond_wait: 观察pthread_cond_t和pthread_mutex_t结构体中变量:__data、__size、__align变化

pthread_cond_signal和pthread_cond_wait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));pthread_mutex_lock(&mutex);//1.如果不调用pthread_cond_signal(&cond)函数发信号,永远死等.pthread_cond_wait(&cond, &mutex);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.sleep(1);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*(reinterpret_cast<int*>(&(cond.__data))));printf("%s() [%d], cond.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__size))));printf("%s() [%d], cond.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__align))));printf("%s() [%d], mutex.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__data))));printf("%s() [%d], mutex.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__size))));printf("%s() [%d], mutex.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__align))));//pthread_cond_signal(&cond);//仅可以唤醒一个线程pthread_cond_broadcast(&cond);//可以唤醒全部线程printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));printf("%s() [%d], cond.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__size))));printf("%s() [%d], cond.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__align))));printf("%s() [%d], mutex.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__data))));printf("%s() [%d], mutex.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__size))));printf("%s() [%d], mutex.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__align))));sleep(2);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));thread.join();return 0;
}

打印:

线程等待信号到来...
operator()() [16], cond.__data = 0
main() [27], cond.__data = 2
main() [28], cond.__data = 2
main() [30], cond.__size = 2
main() [31], cond.__align = 2
main() [33], mutex.__data = 0
main() [34], mutex.__size = 0
main() [35], mutex.__align = 0
main() [40], cond.__data = 3
main() [41], cond.__size = 3
main() [42], cond.__align = 3
main() [44], mutex.__data = 0
main() [45], mutex.__size = 0
main() [46], mutex.__align = 0
operator()() [20], cond.__data = 3
Thread timed wait for 10s.
main() [49], cond.__data = 3

总结:
在进入线程后,信号没来到之前 cond.__data=0;
当进入main进程时,cond.__data=2;
当pthread_cond_signal(&cond)发送信号后,cond.__data=3,然后线程中的pthread_cond_wait(&cond, &mutex)收到cond.__data=3的信号,
立即释放互斥锁,解除阻塞,程序向下运行,到main函数结束。

v6.0 观察pthread_cond_timedwait:pthread_cond_t和pthread_mutex_t结构体中变量:__data、__size、__align变化

pthread_cond_signal和pthread_cond_timedwait用法

#include <iostream>
#include <thread>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
using namespace std;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int main() {//1.给pthread_cond_wait和pthread_cond_timedwait发信号(它俩是成对出现的),使其后边的代码可以执行.std::thread thread = std::thread([&]() {cout << "线程等待信号到来..." << endl;struct timeval now;struct timespec outtime;gettimeofday(&now, NULL);outtime.tv_sec = now.tv_sec + 10;//如果没有等到信号,则超过10s后自动处理.outtime.tv_nsec = now.tv_usec * 1000;pthread_mutex_lock(&mutex);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));//2.可以设置超时时间,一旦超过设定时间,自动执行pthread_cond_timedwait函数后边的代码,它不受pthread_cond_signal的影响.pthread_cond_timedwait(&cond, &mutex, &outtime);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));cout << "Thread timed wait for 10s." << endl;pthread_mutex_unlock(&mutex);});sleep(1);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*(reinterpret_cast<int*>(&(cond.__data))));printf("%s() [%d], cond.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__size))));printf("%s() [%d], cond.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__align))));printf("%s() [%d], mutex.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__data))));printf("%s() [%d], mutex.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__size))));printf("%s() [%d], mutex.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__align))));//pthread_cond_signal(&cond);//仅可以唤醒一个线程pthread_cond_broadcast(&cond);//可以唤醒全部线程printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));printf("%s() [%d], cond.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__size))));printf("%s() [%d], cond.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__align))));printf("%s() [%d], mutex.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__data))));printf("%s() [%d], mutex.__size = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__size))));printf("%s() [%d], mutex.__align = %d\n",__FUNCTION__,__LINE__,*((int*)(&(mutex.__align))));sleep(2);printf("%s() [%d], cond.__data = %d\n",__FUNCTION__,__LINE__,*((int*)(&(cond.__data))));thread.join();return 0;
}

打印

线程等待信号到来...
operator()() [23], cond.__data = 0
main() [33], cond.__data = 2
main() [34], cond.__data = 2
main() [37], cond.__size = 2
main() [38], cond.__align = 2
main() [40], mutex.__data = 0
main() [41], mutex.__size = 0
main() [42], mutex.__align = 0
main() [46], cond.__data = 3
main() [47], cond.__size = 3
main() [48], cond.__align = 3
main() [50], mutex.__data = 0
main() [51], mutex.__size = 0
main() [52], mutex.__align = 0
operator()() [26], cond.__data = 3
Thread timed wait for 10s.
main() [55], cond.__data = 3

总结:
在进入线程后,信号没来到之前 cond.__data=0;
当进入main进程时,cond.__data=2;
当pthread_cond_signal(&cond)发送信号后,cond.__data=3,然后线程中的pthread_cond_wait(&cond, &mutex)收到cond.__data=3的信号,
立即释放互斥锁,解除阻塞,程序向下运行,到main函数结束。

3.总结

所以不管是pthread_cond_signal、pthread_cond_broadcast发送信号给pthread_cond_wait,还是pthread_cond_timedwait,最终信号发生变化的pthread_cond_t是的结构体变量__data字段,是它发生的变化,解除线程的阻塞状态。

这篇关于C语言之pthread_cond_t信号变化探究总结(八十)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/u010164190/article/details/131996061
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/161043

相关文章

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

$在R语言中的作用示例小结

《$在R语言中的作用示例小结》在R语言中,$是一个非常重要的操作符,主要用于访问对象的成员或组件,它的用途非常广泛,不仅限于数据框(dataframe),还可以用于列表(list)、环境(enviro... 目录1. 访问数据框(data frame)中的列2. 访问列表(list)中的元素3. 访问jav

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服