条件变量函数pthread_cond_timedwait实现业务场景

简介: 条件变量函数pthread_cond_timedwait实现业务场景

工作中在进行通信业务开发时,遇到一种超时时间内收到回复做处理的业务场景,使用锁+条件变量实现

1:互斥锁和自旋锁接口梳理

1:条件变量通常配合互斥锁一起使用:

相关定义:

       pthread_mutex_t g_mutex;

       pthread_cond_t g_cond;

相关初始化:

       1:函数初始化/销毁:

           pthread_mutex_init(&g_mutex, NULL);

           pthread_cond_init(&g_cond, NULL);

           pthread_cond_destroy(&g_cond);

           pthread_mutex_destroy(&g_mutex);

       2:静态初始化: ==》不用关注释放

           pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;

           memcpy(&g_cond, &blank_cond, sizeof(pthread_cond_t));

           pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;

           memcpy(&g_mutex, &blank_mutex, sizeof(pthread_mutex_t));

相关使用:

       1:互斥锁加锁/解锁相关函数

           pthread_mutex_lock(&g_mutex);     //加锁

           pthread_mutex_unlock(&g_mutex); //解锁

       2:条件变量相关函数

           pthread_cond_broadcast(&g_cond);  //唤醒所有加锁线程

           pthread_cond_signal(&g_cond);     //唤醒其中一个加锁线程

           pthread_cond_wait(&g_cond, &g_mutex); //没有唤醒一直等待

           pthread_cond_timedwait(&g_cond, &g_mutex, &outtime);

               //等待唤醒,如果超过定义的时间,则也可以运行

               //如果是超时唤醒,返回值非0

2:自选锁的一些梳理

数据结构:

       pthread_spinlock_t spinlock;

相关接口:

       int pthread_spin_init(pthread_spinlock_t *, int);

       int pthread_spin_destroy(pthread_spinlock_t *);

       

       int pthread_spin_lock(pthread_spinlock_t *);

       int pthread_spin_unlock(pthread_spinlock_t *);

       int pthread_spin_trylock(pthread_spinlock_t *);

初始化时第二个参数指定:

       PTHREAD_PROCESS_SHARED:该自旋锁可以在多个进程中的线程之间共享。

       PTHREAD_PROCESS_PRIVATE: 仅初始化本自旋锁的线程所在的进程内的线程才能够使用该自旋锁。

2:相关测试代码:

//对条件变量锁进行测试 超时等待
/*********************************************
多个线程通信,要实现一种唤醒或者超时唤醒的处理,
pthread_cond_timedwait 进行测试
实现方案:
  申请两个线程,同样的逻辑进行测试
********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
//两个线程同样的回调
void* thread_callback(void* arg);
int main()
{
  //初始化全局锁和条件变量
  pthread_mutex_init(&g_mutex, NULL);
  pthread_cond_init(&g_cond, NULL);
  pthread_t t[2];
  //创建两个线程执行回调
  for(int i=0; i<2; i++)
  {
    int ret = pthread_create(&t[i], NULL, thread_callback, (void*)1);
    if(ret != 0)
    {
      printf("pthread_create failed. %d \n", ret);
      return -1;
    }
  }
  sleep(2);
  //主线程实现对线程回调函数中的阻塞等待进行唤醒
  pthread_mutex_lock(&g_mutex);
  pthread_cond_signal(&g_cond); //唤醒一个
  pthread_mutex_unlock(&g_mutex);
  //相关等待及销毁处理
  for(int i = 0; i<2; i++)
  {
    pthread_join(t[i], NULL);
  }
  pthread_cond_destroy(&g_cond);
  pthread_mutex_destroy(&g_mutex);
  return 0;
}
void* thread_callback(void* arg)
{
  //这里两个线程都用pthread_cond_timedwait 进行等待唤醒
  //两种不同的获取时间的方式
  struct timeval now;
  struct timespec outtime;
  gettimeofday(&now, NULL);
  outtime.tv_sec = now.tv_sec + 5; //s
    outtime.tv_nsec = now.tv_usec * 1000; //微妙转为纳秒
    int ret = -1;
    //锁+条件变量实现线程的阻塞一定时间, 或者被唤醒
    pthread_mutex_lock(&g_mutex);
    //等待一定的时间,进行唤醒
  ret = pthread_cond_timedwait(&g_cond, &g_mutex, &outtime);
  pthread_mutex_unlock(&g_mutex);
  printf("pthread_cond_timedwait return %d \n", ret);
  return NULL;
}

代码运行结果:

可以看出,超时返回值非0

pthread_cond_timedwait return 0 
pthread_cond_timedwait return 110

 

目录
相关文章
|
Ubuntu Linux 编译器
openssl 的编译(linux、Ubuntu) 和 交叉编译(arm、Hi3531A)的问题分析、解决
openssl 的编译(linux、Ubuntu) 和 交叉编译(arm、Hi3531A)的问题分析、解决
3369 0
|
5月前
|
Rust 安全 Ubuntu
手把手教你用bindgen:让Rust轻松调用C库
bindgen是Rust官方推荐的FFI绑定生成工具,可自动将C/C++头文件转换为安全、正确的Rust FFI代码,精准处理类型映射、内存布局与符号导出。本文以bzip2为例,详解从环境配置、build.rs脚本编写到压缩/解压缩功能验证的完整实践流程。
|
11月前
|
存储 人工智能 Shell
Lua与C语言接口编程实战指南:打造高性能、灵活的程序
本文深入介绍了 Lua 与 C 语言的交互机制,重点分析了 Lua 作为胶水语言在嵌入式系统、游戏开发(如 Skynet、OpenResty)中的应用。内容涵盖 Lua 环境搭建、虚拟栈管理、C 与 Lua 的相互调用、闭包、Userdata 和注册表的使用等核心技术,并结合代码示例讲解了如何在实际项目中实现 Lua 与 C 的高效交互,适合希望掌握 Lua 扩展与嵌入开发的工程师参考学习。
1243 0
|
人工智能 NoSQL C语言
程序又崩了?一招精准定位段错误!
在C/C++开发中,程序崩溃(如段错误)是常见问题,但快速定位崩溃原因却颇具挑战。本文介绍了一种精准定位崩溃问题的方法:通过捕获异常信号(如SIGSEGV),结合`backtrace()`和`abi::__cxa_demangle()`打印堆栈信息,从而快速定位问题接口。相比增加日志或生成coredump文件,此方法更高效且无副作用。实现时需注意编译选项(如`-O0 -g -rdynamic`)以保留符号信息,并处理C++名称修饰问题。
1046 0
|
Java Linux
【linux线程(三)】生产者消费者模型详解(多版本)
【linux线程(三)】生产者消费者模型详解(多版本)
|
存储 NoSQL Linux
linux之core文件如何查看和调试
通过设置和生成 core 文件,可以在程序崩溃时获取详细的调试信息。结合 GDB 等调试工具,可以深入分析 core 文件,找到程序崩溃的具体原因,并进行相应的修复。掌握这些调试技巧,对于提高程序的稳定性和可靠性具有重要意义。
8235 6
|
Unix Linux 数据处理
Linux命令stty详解
`stty`是Linux命令,用于设置和查看终端参数,如波特率、字符处理和控制字符。它直接与终端驱动交互,支持多种选项以适应不同的配置需求。例如,`stty -a`显示当前设置,`stty -echo`关闭回显,`stty 115200 cs8`调整波特率和字符大小。注意修改设置可能影响终端行为,建议先备份(`stty -g`)并谨慎操作。查阅手册页以获取详细信息。
|
Ubuntu Linux 程序员
交叉编译valgrind在嵌入式设备上调试程序
交叉编译valgrind在嵌入式设备上调试程序