您的位置:首页 > 运维架构 > Linux

LInux线程条件变量的使用

2016-07-27 00:00 585 查看
/*
*生产者消费者问题
* */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#define MAX_STOCK 20//仓库容量
char g_storage[MAX_STOCK];
size_t g_stock=0;//当前库存
//互斥量
pthread_mutex_t g_mtx=PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t g_full=PTHREAD_COND_INITIALIZER;//满仓
pthread_cond_t g_empty=PTHREAD_COND_INITIALIZER;//空仓
//显示库存
void show(const char*who,const char*op,char prod)
{
printf("%s:",who);
size_t i;
for(i=0;i<g_stock;++i)
printf("%c",g_storage[i]);
printf("%s%c\n",op,prod);
}
//生产者线程
void *producer(void*arg)
{
const char *who=(const char*)arg;
for(;;)
{
pthread_mutex_lock (&g_mtx);
if(g_stock>=MAX_STOCK)
{
printf("%s:满仓\n",who);
pthread_cond_wait(&g_full,&g_mtx);

}
char prod='A'+rand()%26;
show(who,"<-",prod);
g_storage[g_stock++]=prod;
pthread_cond_signal(&g_empty);
pthread_mutex_unlock(&g_mtx);
usleep((rand()%100)*1000);
}
return NULL;
}
//消费者线程
void*customer(void*arg)
{
// usleep(10000);
const char*who=(const char*)arg;
for(;;)
{
pthread_mutex_lock(&g_mtx);
if(!g_stock)
{
printf("%s:空仓!\n",who);
pthread_cond_wait(&g_empty,&g_mtx);
}
char prod=g_storage[--g_stock];
show(who,"->",prod);
pthread_cond_signal(&g_full);
pthread_mutex_unlock(&g_mtx);
usleep((rand()%100)*1000);
}
return NULL;
}
int main(){
srand(time(NULL));
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_t tid;
pthread_create(&tid,&attr,producer,"生产者");
pthread_create(&tid,&attr,customer,"消费者");
getchar();
return 0;
}

以上的代码描述的是生产者消费者问题的解决办法。我们通过这段代码来解释条件变量的使用。

首先,生产者线程和消费者线程各自独立执行,我们会遇到两种特殊的情况,1.生产者效率较高使得仓库满;2.消费者效率较高使得仓库空。这两种情况中的任意一种都会导致线程阻塞并占用资源(为了保证同步,我们使用了互斥锁,这使得在线程阻塞后,其它线程拿不到资源)。而通过使用条件变量可以使得当某个线程出现了任意的两种情况中的一种,该线程阻塞,通过另一个线程改变条件之后,给阻塞的线程发送信号来唤醒阻塞的线程。

接下来我们要说的是pthread_cond_wait和pthread_cond_signal这两个函数。

pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex)函数中的第二个参数是一个互斥量,用于对条件变量保护。该函数会将调用线程阻塞在cond这个条件变量上,将它放在等待条件的线程列表中,同时对互斥锁解锁,是的其它线程可以访问资源,在得到其它线程对于cond所发出的信号后,该函数立马返回,并再次加锁。

pthread_cond_signal(pthread_cond_t *restrict cond)这个函数就是用来给阻塞的线程发送信号来唤醒等待cond条件的线程。

通过这两个函数便实现了线程间的同步。而这两个函数的实际功能就是一个阻塞线程,另一个唤醒线程。

对照这上面的生产者消费者模型就是例如当生产者生产过剩,使得仓库满,此时生产者线程阻塞在g_full这个条件变量上,而消费者线程消费后改变了条件状态,通过发送信号来唤醒等待g_full条件的线程,此时生产者又可以继续生产。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: