Linux 线程 1.3 — 条件变量

条件变量相关 API

条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。

条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。

在使用条件变量之前,必须先对它进行初始化。由pthread_cond_t 数据类型表示的条件变量可以用两种方式进行初始化,可以把常量 PTHREAD_COND_INITIALIZER 赋给静态分配的条件变量,但是如果条件变量是动态分配的,则需要使用pthread_cond_init 函数对它进行初始化。
在释放条件变量底层的内存空间之前,可以使用 pthread_cond_destroy 函数对条件变量进行反初始化(deinitialize)。

1. 创建及销毁条件变量

#include <pthread.h>
	int pthread_cond_init(pthread_cond_t *restrict cond, 
							const 	pthread_condattr_t *restrict attr);
	int pthread_cond_destroy(pthread_cond_t cond);
 返回:若成功返回0,否则返回错误编号

除非需要创建一个具有非默认属性的条件变量,否则pthread_cond_init函数的attr参数可以设置为NULL。<我们将在12.4.3节中讨论条件变量属性。—— UNIX 环境高级编程 >
我们使用pthread_cond_wait等待条件变量变为真。如果在给定的时间内条件不能满足,那么会生成一个返回错误码的变量。

2. 等待

#include <pthread.h>
	int pthread_cond_wait(pthread_cond_t *restrict cond, 					
						  pthread_mutex_t *restrict mutex);
	int pthread_cond_timedwait(pthread_cond_t *restrict cond, 
								pthread_mutex_t *rest99rict mutex, 
								cond struct timespec *restrict timeout);
 返回:若成功返回0,否则返回错误编号

pthread_cond_wait 等待条件 变为真(即触发),如果在给定的时间内,条件不能满足,那么会生成一个 代表一个出错码的返回变量。
传递给 pthread_cond_wait 的互斥量对条件进行保护,调用者把锁住的互斥量传给函数,函数自动把调用线程放到等待条件的线程列表上,对互斥量解锁,这样,就关闭了条件检查 和 线程进入休眠状态等待条件改变 这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。 pthread_cond_wait 返回时,互斥量再次被锁住。

pthread_cond_timedwait 函数的功能与 pthread_cond_wait 函数相似,只是多了一个超时(tsptr),超时值指定了我们愿意等待多长时间,它通过 timespec 结构指定。

3. 触发

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t * cond);
int pthread_cond_broadcast(pthread_cond_t * cond);
// 返回:若成功返回0,否则返回错误编号

这两个函数可以用于通知线程条件已经满足。 pthread_cond_signal 函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast 函数将唤醒等待该条件的所有进程。

注意一定要在改变条件状态以后再给线程发信号。

上代码做例子吧,

这节课(线程最后一节)还是重做一遍吧,很多东西,我没有写在这篇博文中,(别问,问就是 废物,记得提醒我写,顺带抽我一巴掌)

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

//       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//                          void *(*start_routine) (void *), void *arg);
pthread_cond_t cond;
pthread_mutex_t mutex;
// 创建一个锁的全局变量
int g_data = 0;

void * funcl1(void * arg){

        printf("this is pthread t1, t1 的 ID 为 : %ld \n",pthread_self());
        //errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定义
。查看错误代码errno是调试程序的一个重要方法。当linux C api函数发生异常时,一般会将errno变量(需include errno.h)赋一个整数值,不同的值表示不同的含义,可以通过查看该值推>测出错的原因。在实际编程中用这一招解决了不少原本看来莫名其妙的问题。
        printf("t1's 参数为 %d \n",*(int *)arg);

        while(1){
                pthread_cond_wait(&cond,&mutex); // 首先要创建一个 条件变量
                // 我们想要让 线程1 来判断 g_data 是否等于1 如果等于,那么就打印这
一句话。              
                if(g_data == 3){
                        printf("g_data == 3;  t1 quit ===============\n");
                                }
                printf("t1 = %d \n",g_data);
                g_data = 0;
                sleep(1);
        }
}

void * funcl2(void * arg){

        printf("this is pthread t2, t2 的 ID 为 : %ld \n",pthread_self());
        //errno 是记录系统的最后一次错误代码。代码是一个int型的值,在errno.h中定  
        printf("t2's 参数为 %d \n",*(int *)arg);

        while(1){

                printf("t2 : %d \n",g_data);
                pthread_mutex_lock(&mutex);
                g_data++;
                pthread_mutex_unlock(&mutex);

                if(g_data == 3){
                        pthread_cond_signal(&cond);
                }

                pthread_mutex_unlock(&mutex);
                sleep(1);
        }
}

int main(){

        int ret;
        pthread_t t1;
        pthread_t t2;
        int * arg;
        *arg =  100;

        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&cond,NULL);

        ret = pthread_create(&t1,NULL,funcl1,(void *)arg);
        if(ret == 0){
                printf("创建线程1 成功 \n");
        }

        ret = pthread_create(&t2,NULL,funcl2,(void *)arg);
        if(ret == 0){
                printf("创建线程2 成功 \n");
        }

        printf("main : %ld  \n",pthread_self());

        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);

        return 0;
}

运行结构

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值