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;
}

代码演示结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值