|
5#
楼主 |
发表于 2016-9-3 18:01:49
|
只看该作者
关于线程互斥的时候使用条件变量的研究
百度百科的解释:条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。(请注意这句话!否则你会纠结为什么当在一个线程中给出条件信号后,正在等待的线程不会立马响应这个条件)
两个关键的函数pthread_cond_wait()和pthread_cond_signal(),前者用于在一个线程中告诉线程等待条件变量的到来,等待的过程线程将会处于阻塞状态,而后者则是在另外一个线程中激发某一个条件,告诉正在等待这个条件产生的线程你可以干活了。pthread_cond_wait()的函数原型为:int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex),可以看出来这和互斥锁mutex有关,这就是上面那句标红了的话的原因。按我们的思维来讲,当条件给出后应该要立马就去响应啊,但是如果这样的话就会对某些公共的资源(如全局变量)形成竞争!出现同时又两个或两个以上的线程对同一个资源进行操作,这是不允许的。为解决这一问题,于是将条件变量与互斥锁一起使用,双重保险,以避免多个线程同时操作一个资源的情况,即使条件已经给出来了,如果锁还没有被其他线程释放,那么线程将会继续等待。
举个例子:有一个全局变量i,thread1中将i从1自加到9,当i是3的倍数的时候就产生条件,即执行pthread_cond_signal;在thread2中判断i的情况,当i不为3的倍数的时候就等待,知道i为3的倍数的才执行操作。
给出代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; /*初始化条件变量*/
void *thread1(void *); /*线程a函数声明*/
void *thread2(void *); /*线程b函数声明*/
int i=1;/*测试用的全局变量*/
int main(void)
{
pthread_t t_a; /*线程a标识符*/
pthread_t t_b; /*线程b标识符*/
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/
pthread_join(t_b, NULL);/*等待进程t_b结束*/
pthread_mutex_destroy(&mutex); /*销毁互斥锁*/
pthread_cond_destroy(&cond); /*销毁条件变量*/
exit(0);
}
void *thread1(void *junk)
{
for(i=1;i<=9;i++) {
pthread_mutex_lock(&mutex);//
if(i%3==0){
pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
}
printf("thead1:%d\n",i);
pthread_mutex_unlock(&mutex);//*解锁互斥量*/
printf("Thread1 Up Unlock Mutex\n");
sleep(1);
}
}
void *thread2(void *junk)
{
while(i<9)
{
pthread_mutex_lock(&mutex);
if(i%3!=0) {
pthread_cond_wait(&cond,&mutex);/*等待*/
}
printf("thread2:%d\n",i);
pthread_mutex_unlock(&mutex);
printf("Thread2 Down Ulock Mutex\n");
sleep(1);
}
}
编译之后,执行可执行文件,得到如下的结果,可以看到屏幕上面基本是按顺序打印出来提示信息,就感觉好像是当thread1执行pthread_cond_signal(&cond)后,thread2就立马结束了阻塞状态进入到就绪态,再到执行状态。
但将thread1改成这样:
void *thread1(void *junk)
{
for(i=1;i<=9;i++) {
pthread_mutex_lock(&mutex);//
if(i%3==0){
/*在执行pthread_cond_signal后,将线程休眠3秒后再将mutex解锁*/
pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
printf("cond_signal! now unlock mutex atter 3s\n");
sleep(3);
pthread_mutex_unlock(&mutex);//*解锁互斥量*/
} else{
printf("thead1:%d\n",i);
pthread_mutex_unlock(&mutex);//*解锁互斥量*/
printf("Thread1 Up Unlock Mutex\n");
}
/*为了观察现象,每次循环都将线程休眠5秒*/
sleep(5);
}
}
将i是3的倍数和不是3的倍数的两种情况分开,分别执行解锁操作pthread_mutex_unlock(&mutex),重新编译后,再执行程序,可以看到在i为3的倍数的情况下,执行了pthread_cond_signal(&cond)之后,thread2并没有立马打印出信息,而是在thread1执行pthread_cond_signal(&cond)后,在睡眠3秒,最后执行完了pthread_mutex_unlock(&mutex),将mutex从thread1中解锁后,thread2才从阻塞态退出的。
|
|