Linux线程间通信-条件变量


从本篇开始对多线程通信的知识点进行整理,本篇主要介绍条件变量,有什么错误和建议请留言指教。有关前文 多线程基础的整理请点此处

一、条件变量的介绍

条件变量本质也是一个全局变量,它的功能是阻塞线程,直至接收到“条件成立”的信号后,被阻塞的线程才能继续执行。

#include <pthreadtypes.h>
typedef union
{
  struct __pthread_cond_s __data;
  char __size[__SIZEOF_PTHREAD_COND_T];
  __extension__ long long int __align;
} pthread_cond_t;

二、条件变量的创建和使用

相关操作接口有:

函数声明作用
int pthread_cond_init (pthread_cond_t *cond, const 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_signal (pthread_cond_t *cond)唤醒一个被条件变量阻塞的线程
int pthread_cond_broadcast (pthread_cond_t *cond)唤醒所有被条件变量阻塞的线程

下面这张图很清晰的展示了条件变量的用法和操作过程。
在这里插入图片描述
条件变量的使用中存在三个变量,一个互斥锁,一个条件变量,和另外一个需要判断其状态的变量(后面简称其为状态变量),一般执行顺序为:

线程A中

  • 对互斥锁加锁
  • 判断状态变量状态是否满足某个条件
  • 若状态不满足条件则调用pthread_cond_wait函数,该函数中:
    • 对互斥锁解锁
    • 阻塞当前线程,直到收到pthread_cond_signal信号
    • 收到pthread_cond_signal后,再次对互斥锁加锁
  • 再次判断状态变量状态是否满足某个条件
  • 若状态变量满足条件则对互斥锁解锁,继续往下执行,否则再次进入pthread_cond_wait

线程B中

  • 对互斥锁加锁
  • 使状态变量满足线程A中的条件
  • 调用pthread_cond_signal函数,给线程A发送条件变量信号
  • 对互斥锁解锁

将上述逻辑写成代码就是:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;	// 互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;			// 条件变量
UINT32 status = 0;																						// 状态变量

void  thread_A(){
		pthread_mutex_lock(&mutex);
		while( 100 != status){
				pthread_cond_wait(&cond, &mutex)
		}
		pthread_mutex_unlock(&mutex);
		/* 接着执行其它代码 */
}

void  thread_B(){
		pthread_mutex_lock(&mutex);
		status = 100;
		pthread_cond_signal(&cond)
		pthread_mutex_unlock(&mutex);
		/* 继续执行其它代码 */
}

三、代码实例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/*初始化条件变量*/
void *thread1(void *);
void *thread2(void *);
int i=1, res = 0;
int main(void){    
	pthread_t t_a, t_b;    
	pthread_attr_t attr1, attr2;    
	struct sched_param param;
    int other_max = sched_get_priority_max(SCHED_OTHER);    
    int other_min = sched_get_priority_min(SCHED_OTHER);    
    int fifo_max = sched_get_priority_max(SCHED_FIFO);    
    int fifo_min = sched_get_priority_min(SCHED_FIFO);    
    int rr_max = sched_get_priority_max(SCHED_RR);    
    int rr_min = sched_get_priority_min(SCHED_RR);
    printf("other_max:%d\n", other_max);    
    printf("other_min:%d\n", other_min);    
    printf("fifo_max:%d\n", fifo_max);    
    printf("fifo_min:%d\n", fifo_min);    
    printf("rr_max:%d\n", rr_max);    
    printf("rr_min:%d\n", rr_min);
    if (0 != pthread_attr_init(&attr1)){        
    	printf("attr1 init error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_attr_init(&attr2)){        
    	printf("attr2 init error!\n");        
    	exit(0);    
    }    
    /*设置调度策略*/    
    if (0 != pthread_attr_setschedpolicy(&attr1, SCHED_FIFO)){        
    	printf("attr1 setschedpolicy error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_attr_setschedpolicy(&attr2, SCHED_FIFO)){        
    	printf("attr2 setschedpolicy error!\n");        
    	exit(0);    
    }    
    /*设置线程1优先级*/    
    param.sched_priority = 50;    
    if (0 != pthread_attr_setschedparam(&attr1,&param)){        
    	printf("attr1 setschedparam error!\n");        
    	exit(0);    
    }
    if (0 != pthread_attr_setinheritsched(&attr1,PTHREAD_EXPLICIT_SCHED)){        
    	printf("attr1 setinheritsched error!\n");        
    	exit(0);   
    }    
    /*设置线程2优先级*/    
    param.sched_priority = 40;    
    if (0 != pthread_attr_setschedparam(&attr2,&param)){        
    	printf("attr2 setschedparam error!\n");        
    	exit(0);    
    }
    if (0 != pthread_attr_setinheritsched(&attr2,PTHREAD_EXPLICIT_SCHED)){        
    	printf("attr2 setinheritsched error!\n");        
    	exit(0);    
    }
    res = pthread_create(&t_a,&attr2,thread2,(void *)NULL);    
    /*创建进程t_a*/    
    if (0 != res){        
    	printf("create thread t_a error! ErrNo : %d\n", res);        
    	exit(0);    
    }    
    // sleep(1);    
    res = pthread_create(&t_b,&attr1,thread1,(void *)NULL);    
    /*创建进程t_b*/    
    if (0 != res){        
    	printf("create thread t_a error! ErrNo : %d\n", res);        
    	exit(0);    
    }    
    if (0 != pthread_join(t_a, NULL)){        
    	printf("t_a pthread_join error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_join(t_b, NULL)){       
    	printf("t_b pthread_join error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_attr_destroy(&attr1)){        
    	printf("t_a pthread_attr_destroy error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_attr_destroy(&attr2)){        
    	printf("t_b pthread_attr_destroy error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_mutex_destroy(&mutex)){        
    	printf("pthread_mutex_destroy error!\n");        
    	exit(0);    
    }    
    if (0 != pthread_cond_destroy(&cond)){        
    	printf("pthread_cond_destroy error!\n");        
    	exit(0);    
    }    
    exit(0);
}
void *thread1(void *junk){    
	attach_cpu(0);    
	for(i=1; i<=9; ){        
		/*锁住互斥量,使得只有线程2进入wait状态后才能发出signal*/        
		printf("before thread 1 lock\n");        
		res = pthread_mutex_lock(&mutex);        
		if (0 != res){            
			printf("pthread_mutex_lock error, errorNo: %d\n", res);            
			exit(0);        
		}        
		i++;        
		if(0 == i%3){            
			printf("signal\n");           
			/*条件改变,发送信号,通知t_b进程*/            
			if (0 != pthread_cond_signal(&cond)){                
				printf("pthread_cond_signal error!\n");                
				exit(0);            
			}        
		}else{            
			printf("thread1:%d\n", i);        
		}
        res = pthread_mutex_unlock(&mutex);        
        if (0 != res){            
        	printf("pthread_mutex_unlock error, errorNo: %d\n", res);            
        	exit(0);        
        } 
        usleep(10);    
	}
}
void *thread2(void *junk){    
	attach_cpu(0);    
	while(i < 9){        
		printf("before lock in thread 2, i : %d\n", i);        
		res = pthread_mutex_lock(&mutex);        
		if (0 != res){            
			printf("pthread_mutex_lock error, errorNo: %d\n", res);            
			exit(0);        
		}        
		if(0 != i%3){            
			printf("wait\n");            
			if (0 != pthread_cond_wait(&cond,&mutex)){                
				printf("pthread_cond_wait error!\n");                
				exit(0);           
			}            
			printf("after wait\n");        
		}        
		printf("thread2:%d\n", i);        
		res = pthread_mutex_unlock(&mutex);        
		if (0 != res){            
			printf("pthread_mutex_unlock error, errorNo: %d\n", res);            
			exit(0);        
		}         
		usleep(10);    
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值