条件变量(条件锁)

条件变量

注意:条件变量和互斥变量必须一块使用

应用场景:生产者消费者问题,是线程同步的一种手段,使多个线程合理的使用资源

必要性:为了实现等待某个资源,让线程休眠。提高运行效率

初始化:

静态初始化

pthread_cond_t   cond = PTHREAD_COND_INITIALIZER;        //初始化条件变量

pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;         //初始化互斥量

动态初始化

pthread_cond_t cond;

pthread_cond_init(&cond);//动态初始化条件变量

pthread_mutex_t mutex

pthread_mutex_init(&mutex);动态初始化互斥量

生产资源线程:

pthread_mutex_lock(&mutex);        //加锁

临界区:产生临界资源(临界资源不可共享)

pthread_cond_sigal(&cond);         //通知一个消费线程

或者

pthread_cond_broadcast(&cond);         //广播通知多个消费线程

pthread_mutex_unlock(&mutex);        //释放锁

void *taxiarv(void *arg){
	printf("taxi arrived pthread\n");
	pthread_detach(pthread_self());
	taxi tx;
	int i=1;
	while(1){
		tx=(taxi)malloc(sizeof(taxi_t));
		tx->num=i++;
		printf("taxi  %d  comming\n",tx->num);
		pthread_mutex_lock(&lock);
		tx->next=Head;
		Head=tx;
		pthread_cond_signal(&hastaxi);
		pthread_mutex_unlock(&lock);
		sleep(1);
	}
	pthread_exit(0);
}

消费者线程:

pthread_mutex_lock(&mutex);//加锁

while (如果没有资源){   

pthread_cond_wait(&cond, &mutex);         //加while是为了防止惊群效应

}

临界区:消费临界资源

pthread_mutex_unlock(&mutex);         //释放锁

void *taketaxi(void *arg){
	printf("take taxi pthread\n");
	pthread_detach(pthread_self());
	taxi tx;
	while(1){
		pthread_mutex_lock(&lock);
		while(Head==NULL){
			pthread_cond_wait(&hastaxi,&lock);
		}
		tx=Head;
		Head=tx->next;
		printf("take taxi %d\n",tx->num);
		free(tx);
		pthread_mutex_unlock(&lock);
	}
	pthread_exit(0);
}

注意:

1 pthread_cond_wait(&cond, &mutex),在没有资源等待是先unlock解锁,再休眠,等资源到了,再lock上锁

所以pthread_cond_wait 和 pthread_mutex_lock ,pthread_mutex_unlock 必须配对使用。

2  如果pthread_cond_signal或者pthread_cond_broadcast 早于 pthread_cond_wait ,则有可能会丢失信号。

3 pthead_cond_broadcast 信号会被多个线程收到,这叫线程的惊群效应。所以需要加上判断条件while循环。

注意:一个线程产生一个资源,对其它若干线程发送信号,只有其中一个线程能获取到资源,如果不加while判断,其余线程将会拿到空指针;

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
typedef struct taxi{
	struct taxi *next;
	int num;
}*taxi,taxi_t;
taxi Head=NULL;
pthread_cond_t hastaxi=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
void *taxiarv(void *arg);
void *taketaxi(void *arg);
int main(){
	pthread_t tid1,tid2;
	pthread_create(&tid1,NULL,taxiarv,NULL);
	pthread_create(&tid2,NULL,taketaxi,NULL);
	while(1){
		sleep(1);
	}
}
void *taxiarv(void *arg){
	printf("taxi arrived pthread\n");
	pthread_detach(pthread_self());
	taxi tx;
	int i=1;
	while(1){
		tx=(taxi)malloc(sizeof(taxi_t));
		tx->num=i++;
		printf("taxi  %d  comming\n",tx->num);
		pthread_mutex_lock(&lock);
		tx->next=Head;
		Head=tx;
		pthread_cond_signal(&hastaxi);
		pthread_mutex_unlock(&lock);
		sleep(1);
	}
	pthread_exit(0);
}
void *taketaxi(void *arg){
	printf("take taxi pthread\n");
	pthread_detach(pthread_self());
	taxi tx;
	while(1){
		pthread_mutex_lock(&lock);
		while(Head==NULL){
			pthread_cond_wait(&hastaxi,&lock);
		}
		tx=Head;
		Head=tx->next;
		printf("take taxi %d\n",tx->num);
		free(tx);
		pthread_mutex_unlock(&lock);
	}
	pthread_exit(0);
}

相关函数介绍

int pthread_cond_wait(pthread_cond_t *restrict cond,

           pthread_mutex_t *restrict mutex);

如果不来信号,将会一直等待

参数:

  1. cond:指向待等待的条件变量(pthread_cond_t 类型)的指针。

  2. mutex:指向互斥锁(pthread_mutex_t 类型)的指针。在调用 pthread_cond_timedwait 之前,应该先锁住这个互斥锁,以确保线程安全。

int pthread_cond_timedwait(pthread_cond_t *restrict cond,

           pthread_mutex_t *restrict mutex,

           const struct timespec *restrict abstime);

pthread_cond_timedwait 函数是 POSIX 线程库中用于条件变量等待的函数之一。它会使当前线程在指定的条件变量上等待,直到满足特定条件或者超时。这个函数需要传入三个参数:

  1. cond:指向待等待的条件变量(pthread_cond_t 类型)的指针。

  2. mutex:指向互斥锁(pthread_mutex_t 类型)的指针。在调用 pthread_cond_timedwait 之前,应该先锁住这个互斥锁,以确保线程安全。

  3. abstime:指向 struct timespec 结构的指针,用于指定等待的绝对时间。如果在指定的时间内条件变量没有被满足,线程将会被唤醒。

该函数会在以下情况之一发生时返回:

  • 条件变量被满足。
  • 超时时间到达。
  • 函数被信号中断。

int pthread_cond_signal(pthread_cond_t *cond);

放出信号,可以访问资源(单个发送)

参数:cond:指向待等待的条件变量(pthread_cond_t 类型)的指针。

int pthread_cond_broadcast(pthread_cond_t *cond);

放出信号,可以访问资源(广播发送)

参数:cond:指向待等待的条件变量(pthread_cond_t 类型)的指针。

  • 35
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值