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

Linux条件变量

在 Linux 系统中,pthread_cond_init() 函数和条件变量(Condition Variable)是多线程编程中用于线程同步的核心机制。它们通过协调线程间的等待与通知逻辑,解决共享资源的竞争问题。以下从功能、工作机制、使用场景和注意事项等方面进行详细解析:

一、条件变量的核心概念

条件变量是一种线程同步原语,允许线程在某个条件未满足时进入阻塞状态,并在条件满足时被唤醒。其核心作用包括:

  1. ​等待条件​​:线程通过 pthread_cond_wait() 释放互斥锁并阻塞,直到其他线程发送信号。
  2. ​通知条件​​:其他线程通过 pthread_cond_signal() 或 pthread_cond_broadcast() 触发条件变量,唤醒等待的线程。
  3. ​与互斥锁配合​​:条件变量必须与互斥锁(pthread_mutex_t)结合使用,避免竞争条件(Race Condition)。

二、pthread_cond_init() 函数的作用

pthread_cond_init() 用于动态初始化条件变量,其原型为:

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
  • ​参数​​:
    • cond:指向条件变量的指针。
    • attr:条件变量属性(通常设为 NULL,使用默认属性)。
  • ​返回值​​:成功返回 0,失败返回错误码(如 EINVALEBUSY)。
  • ​初始化方式​​:
    • ​静态初始化​​:直接赋值宏 PTHREAD_COND_INITIALIZER,适用于全局或静态变量。
    • ​动态初始化​​:通过 pthread_cond_init() 动态创建,适用于需要自定义属性的场景(如进程间共享。

三、条件变量的工作机制

1. 线程等待条件(pthread_cond_wait
  • ​步骤​​:
    1. 线程持有互斥锁,检查条件是否满足。
    2. 若条件不满足,调用 pthread_cond_wait() 释放互斥锁并阻塞。
    3. 被唤醒后,重新获取互斥锁并再次检查条件。
  • ​关键特性​​:
    • ​原子性​​:释放锁和阻塞操作是原子的,避免竞争条件。
    • ​虚假唤醒​​:线程可能因系统信号意外唤醒,需用 while 循环而非 if 检查条件。
2. 线程发送信号(pthread_cond_signal/pthread_cond_broadcast
  • pthread_cond_signal​:唤醒一个等待线程(若有多个线程等待,具体唤醒哪个由调度策略决定)。
int pthread_cond_signal(pthread_cond_t *cond);
  • pthread_cond_broadcast​:唤醒所有等待线程,适用于需要批量通知的场景(如生产者-消费者模型)
int pthread_cond_broadcast(pthread_cond_t *cond);
​特性​pthread_cond_signal()pthread_cond_broadcast()
​唤醒线程数量​至少 1 个(可能更多,但规范未定义)所有等待线程
​适用场景​单任务处理(如单资源可用)批量任务处理(如多资源可用)
​性能开销​较低(仅唤醒一个线程)较高(需处理多线程竞争锁)
​虚假唤醒风险​需通过 while 循环检查条件同样需 while 循环检查条件
​调度确定性​可能因优先级或系统策略影响唤醒顺序无确定性,所有线程均被唤醒

代码演示:

#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<string>const int num = 5;
pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;             //全局锁
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;               //全局条件变量
void* wait(void*args)                                          //线程回调函数
{while(true){//加锁pthread_mutex_lock(&gmutex);//条件变量,线程在这里阻塞等待pthread_cond_wait(&gcond,&gmutex);std::string name = static_cast<const char*>(args);usleep(10000); std::cout<<"I am :"<<name<<std::endl;          //解锁pthread_mutex_unlock(&gmutex);}return nullptr;
}int main()
{pthread_t threads[num];                                     //设置线程for(int i=0;i<num;i++)                                      //创建5个线程{char*name = new char[1024];                             //线程名称snprintf(name,1024,"thread-%d",i+1);pthread_create(threads+i,nullptr,wait,(void*)name);     //创建线程usleep(10000);                                          //设置创建线程和条件变量阻塞等待为同一时间}//主线程唤醒阻塞等待while(true){pthread_cond_signal(&gcond);                             //唤醒一个线程std::cout<<"唤醒一个线程..."<<std::endl;sleep(2);}for(int i=0;i<num;i++){pthread_join(threads[i],nullptr);                         //回收}return 0;
}

代码演示结果:

http://www.xdnf.cn/news/7748.html

相关文章:

  • 从零基础到最佳实践:Vue.js 系列(4/10):《Vue Router 路由管理:深入探索与实战应用》
  • 选择合适的Azure数据库监控工具
  • 【Java学习方法】类变量
  • 七彩喜防摔马甲:科技守护银发安全的“隐形铠甲”
  • LabVIEW风机状态实时监测
  • 【前端基础】12、CSS的overflow(visible、hidden、scroll、auto)【注:只有最基础的说明。】
  • AI驱动新增长:亚马逊Rufus广告点击率提升300%的奥秘
  • 微型化GNSS射频前端芯片AT2659S:L1频段多系统支持,SOT23-6封装
  • Python 字典的用法和技巧
  • 设计模式介绍
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Hidden Search Widget (交互式搜索框)
  • 企业网站架构部署与优化-Nginx核心功能
  • Quasar 使用 Pinia 进行状态管理
  • C#SQLServer数据库通用访问类
  • 电子电路:什么是射极电阻?
  • 构建安全的Vue前后端分离架构:利用长Token与短Token实现单点登录(SSO)策略
  • 多线程环境下结构体赋值是否具有原子性?
  • Java 线程池 ThreadPoolExecutor
  • SAP-ABAP:SAP的BAPI_PO_CHANGE功能详解
  • 9 定时任务与周期性调度
  • 活到老学到老-Spring注解-如何创建get和set
  • C++面向对象——多态
  • 进程之IPC通信一
  • 内核常见面试问题汇总
  • PN结的形成及特性
  • 技术派项目——注册登录(用户名密码的方式)
  • 瀚高安全版4.5.8/4.5.9字符串默认按字节存储导致数据无法写入(APP)
  • 前端流行框架Vue3教程:20. 插槽slot(2)
  • leetcode 找到字符串中所有字母异位词 java
  • 牛顿迭代法求解除法