18.线程同步:条件变量cond

1.条件变量

1.条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法。
2.条件变量+互斥锁(一起使用)
	线程同步——互斥锁
	阻塞线程——条件变量

2.条件变量使用场景举例

  举个简单的例子,应用程序A中包含两个线程t1和t2。t1需要在 bool变量test_cond为true时
才能继续执行,而test_cond的值是由t2来改变的,这种情况下,如何来写程序呢?可供选
择的方案有两 种:
  第一种是t1定时的去轮询变量test_cond,如果test_cond为false,则继续休眠;如果test_cond为
 true,则开始执行。
  第二种就是上面提到的条件变量,t1在test_cond为false时调用cond_wait进行等待,t2在改变
test_cond的值后,调用cond_signal,唤醒在等待中的t1,告诉t1 test_cond的值变了,这样t1便可
继续往下执行。
[性能对比分析]
  很明显,上面两种方案中,第二种方案是比较优的。在第一种方案中,在每次轮询时,如果t1休
眠的时间比较短,会导致cpu浪费很厉害;如果t1休眠的时间 比较长,又会导致应用逻辑处理不够
及时,致使应用程序性能下降。第二种方案就是为了解决轮询的弊端而生的。

3.相关函数

pthread_cond_t cond; //条件变量类型

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr); //初始化
int pthread_cond_destroy(pthread_cond_t *cond); //销毁

//当条件不到来时,仅仅只阻塞一定的时长
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex,
              const struct timespec *restrict abstime);
//当条件不到来时,一直阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);

//唤醒[至少一个]阻塞在条件变量上等待的线程
int pthread_cond_signal(pthread_cond_t *cond);
//广播:唤醒[全部]的阻塞在条件变量上等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond); 

注解:pthread_cond_wait 函数剖析

pthread_cond_wait的内部执行原理:
  [1]先对mutex解锁,解锁后再阻塞,一直等待条件到来; //条件没到来时,程序阻塞在pthread_cond_wait处
  [2]当条件到来(被pthread_cond_signal唤醒)时,解除阻塞,与此同时,
pthread_cond_wait再对mutex加锁;之后执行条件满足的操作  
问题:pthread_cond_wait为什么要对mutex解锁?
   (1)使得其他线程有机会进入临界区,等待相同的条件
   (2)使得其他线程有机会进入临界区,对临界资源进行更改

4.使用条件变量的万能公式

线程A(等待条件的线程) 
	pthread_mutex_lock(mutex)         
	while(条件不满足){
	    pthread_cond_wait(&cond);
	} 
	执行条件满足的操作  
	pthread_mutex_unlock(mutex)
----------------------------------------  
线程B(修改条件的线程)
	pthread_mutex_lock(mutex)           
	修改条件
	pthread_mutex_unlock(&mutex);  
	if(条件满足){
		pthread_cond_signal(&cond)
	}

疑问:为什么等待条件的线程的代码中使用while,而不是if
      防止被虚假的唤醒,当是虚假的唤醒操作时,由于使用的while,因此需要再判断一次,
条件不满足时,继续阻塞。

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/83089189
今日推荐