头文件 pthread.h
struct cangku 中定义了空间大小为7的 char 数组。读游标、写游标。非空、非满条件变量。互斥锁。
游标均采用从0 1 2 3 4 5 6 0 1 2...的移动方式。仓库初始化时,读、写游标被置零。条件变量使用函数
pthread_cond_init(¬empty,NULL)进行初始化。
本次示例代码中使用了消费者和生产者这个经典的问题。
首先创建消费者和生产者线程,分别对应的处理函数为consumerf、producerf。
在consumerf函数中,循环从仓库中取出字符显示在控制台上。在每次取字符之前,如果读、写游标重合,
此时仓库为空,那么消费者使用pthread_cond_wait(¬empty,&suo)等待生产者的利用pthread_cond_signal(¬empty)发出非空信号。
读出后将读游标按规则递增。读到z停止。
在producerf函数中,从a循环到z。如果写游标在读游标的前一个位置(按照递增规则),那么循环等待消费者产生的非满信号。
然后写入数据,写游标递增。
无论是消费者还是生产者,在每次执行操作之前,都需要添加互斥锁pthread_mutex_lock(&suo)。操作结束后执行pthread_mutex_unlock(&suo)解锁。
最后使用pthread_cond_destroy(¬empty)进行销毁。
注意事项:pthread_cond_wait(¬empty,&suo)函数需要用到互斥锁。pthread_cond_signal(¬empty)不需要锁。
#include <stdio.h>
#include <pthread.h>
struct cangku//仓库结构体
{
char buf[7];
int readpos;
int writepos;
pthread_cond_t notempty;//条件变量
pthread_cond_t notfull;
pthread_mutex_t suo;
};
void initcangku(struct cangku *ck);
void destroyck(struct cangku *ck);
void consumerf(struct cangku *ck);
void producerf(struct cangku *ck);
int main()
{
pthread_t consumer,producer;
struct cangku ck;
initcangku(&ck);
pthread_create(&consumer,NULL,(void *)&consumerf,&ck);
pthread_create(&producer,NULL,(void *)&producerf,&ck);
pthread_join(producer,NULL);
pthread_join(consumer,NULL);
destroyck(&ck);
return 0;
}
void initcangku(struct cangku *ck)
{
ck->readpos = 0;
ck->writepos = 0;
pthread_cond_init(&ck->notempty,NULL);
pthread_cond_init(&ck->notfull,NULL);
pthread_mutex_init(&ck->suo,NULL);
}
void destroyck(struct cangku *ck)
{
pthread_cond_destroy(&ck->notempty);
pthread_cond_destroy(&ck->notfull);
pthread_mutex_destroy(&ck->suo);
}
void consumerf(struct cangku *ck)
{
while(1)
{
if(ck->buf[ck->readpos] == 'z')
break;
pthread_mutex_lock(&ck->suo);
while(ck->readpos == ck->writepos)
{
pthread_cond_wait(&ck->notempty,&ck->suo);//deng dai tiao jian man zu
}
printf("consumer <- %c\n",ck->buf[ck->readpos]);
ck->readpos++;
if(ck->readpos == 7)
ck->readpos = 0;
pthread_cond_signal(&ck->notfull);
pthread_mutex_unlock(&ck->suo);
}
}
void producerf(struct cangku *ck)
{
int i;
for(i='a';i<='z';i++)
{
pthread_mutex_lock(&ck->suo);
while((ck->writepos+1)%7 == ck->readpos)
{
pthread_cond_wait(&ck->notfull,&ck->suo);
}
ck->buf[ck->writepos] = i;
printf("producer -> %c\n",i);
ck->writepos++;
if(ck->writepos == 7)
ck->writepos = 0;
pthread_cond_signal(&ck->notempty);
pthread_mutex_unlock(&ck->suo);
}
}