pthread_cond_t 究竟有什么花样?

老规矩,一张图胜过1000行注释。
在这里插入图片描述

#include <pthread.h>

pthread_cond_t   cond=PTHREAD_COND_INITIALIZER
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond); 

APUE原文:
“ 调用者把锁住的互斥量传给函数,函数然后自动把调用线程放到等待条件的线程列表上,**对互斥量解锁。**这就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。”
也就是说,使用条件变量的前提是:线程、互斥锁。
起作用大概就是使多线程之间有交互、有限制地运行,防止线程不安全问题。

创建和初始化条件变量

pthread_mutex_t mtx;            //互斥锁是必须的演猿
pthread_mutex_init(&mtx, NULL);
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);

阻塞线程等待通知

while(条件不满足?)
{
    pthread_cond_wait(&cond, &mtx);
}

pthread_cond_wait 函数一旦调用,则线程立即被阻塞,同时所拥有的互斥锁也被释放,线程一直停止在pthread_cond_wait 函数中,直到 pthread_cond_singal 函数通知对应的条件变量时接触阻塞,pthread_cond_wait 运行结束,但是返回的时会申请之前释放的互斥锁。
pthread_cond_timedwait 函数与 pthread_cond_wait 函数功能相同。不过多了一个超时参数。
超时值指定了我们愿意等待多长时间,如果超时到期之后,条件还是没有出现,此函数将重新获取互斥锁,然后返回错误 ETIMEOUT。

/* time.h
struct timespec
{
    __time_t tv_sec;        // 秒
    long int tv_nsec;       // 纳秒,1s = 1000*1000*1000ns
};
*/

struct timespec timeout;
timeout.tv_sec = time(NULL) + 1;//time(NULL);就是返回从1970年元旦午夜0点到现在的秒数,+1相当于等待1秒
timeout.tv_nsec = 0;

int err = pthread_cond_timedwait(&mtx, &timeout);
if(0 != err) {                //没有获得锁
    if(ETIMEDOUT == err) {    //超时
        ......
    }
}

唤醒信号发送

pthread_cond_signal(&cond);
pthread_cond_broadcast(&cond);

pthread_cond_signal 函数:至少能唤醒一个等待该条件的线程。
pthread_cond_broadcast 函数:则唤醒等待该条件的所有线程。
必须注意:最好是在改变条件状态以后再给线程发信号!!!wait 的写法多种多样,但是最常见的还是在 while 中,在 while 被唤醒的线程会因为不满足条件而再次被阻塞!!!

销毁条件变量

pthread_cond_destroy(&cond);

从用法上来看都可以推算出内部肯定是申请过内存的,既然是不再使用的内存就应该被释放掉。

案例
实验内容:控制两个线程打印出:A、B、A、B、A、B……

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

enum PRINK
{
    A = 0,
    B,
};

pthread_mutex_t mtx;
pthread_cond_t  cond;
int flag;

void* A_thread()
{
    while(1)
    {
        pthread_mutex_lock(&mtx);
        while(flag == B)
        {
            pthread_cond_wait(&cond, &mtx);
        }
        FILE *fp = fopen( "test.txt", "a+" );
        fputs("A", fp);
        flag = B;

        fclose( fp );
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mtx);
    }
}

void* B_thread()
{
    while(1)
    {
        pthread_mutex_lock(&mtx);
        while(flag == A)
        {
            pthread_cond_wait(&cond, &mtx);
        }
        FILE *fp = fopen( "test.txt", "a+" );
        fputs("B", fp);
        flag = A;

        fclose( fp );
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mtx);
    }
}

int main(int argc, char **argv)
{
    pthread_t th1;
    pthread_t th2;
    pthread_mutex_init(&mtx, NULL);
    pthread_cond_init(&cond,NULL);

    pthread_create(&th1,NULL,A_thread,NULL);
    pthread_create(&th2,NULL,B_thread,NULL);

    sleep(5);

    pthread_cancel(th1);
    pthread_cancel(th2);
}

运行结果:
在这里插入图片描述
最后发现了一个问题,使用 pthread_cond_t 的打印明显比 单独使用 pthread_mutex_t 多了很多。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值