《UNIX网络编程 卷2》读书笔记(三)

多个生产者,单个消费者,只考虑生产者之间的同步互斥

None.gif#include"unpipc.h"
None.gif
None.gif
#defineMAXNITEMS1000000
None.gif
#defineMAXNTHREADS100
None.gif
ExpandedBlockStart.gifContractedBlock.gif
intnitems;/**//*read-onlybyproducerandconsumer*/
ExpandedBlockStart.gifContractedBlock.gif
structdot.gif{
InBlock.gifpthread_mutex_tmutex;
//互斥信号量
InBlock.gif
intbuff[MAXNITEMS];
InBlock.gif
intnput;//下一个存放元素的下标
InBlock.gif
intnval;//下一个存放的值
ExpandedBlockStart.gifContractedBlock.gif
}
shared=dot.gif{PTHREAD_MUTEX_INITIALIZER};
None.gif
None.gif
void*produce(void*),*consume(void*);
None.gif
None.gif
int
None.gifmain(
intargc,char**argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti,nthreads,count[MAXNTHREADS];
InBlock.gifpthread_ttid_produce[MAXNTHREADS],tid_consume;
InBlock.gif
InBlock.gif
if(argc!=3)
InBlock.giferr_quit(
"usage:prodcons2<#items><#threads>");
InBlock.gifnitems
=min(atoi(argv[1]),MAXNITEMS);//生产者存放的条目数
InBlock.gif
nthreads=min(atoi(argv[2]),MAXNTHREADS);//待创建的生产者线程数
InBlock.gif

InBlock.gifSet_concurrency(nthreads);
//通知线程系统我们希望并发多少线程
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4startalltheproducerthreads*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifcount[i]
=0;//计数器初始化为0
InBlock.gif
Pthread_create(&tid_produce[i],NULL,produce,&count[i]);//创建生产者线程
ExpandedSubBlockEnd.gif
}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4waitforalltheproducerthreads*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifPthread_join(tid_produce[i],NULL);
//等待生产者线程结束
InBlock.gif
printf("count[%d]=%d/n",i,count[i]);
ExpandedSubBlockEnd.gif}

InBlock.gif
//这样做的目的是为了避免生产者和消费者之间的同步问题,这里只考虑生产者之间的同步
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4start,thenwaitfortheconsumerthread*/
InBlock.gifPthread_create(
&tid_consume,NULL,consume,NULL);//创建消费者线程
InBlock.gif
Pthread_join(tid_consume,NULL);
InBlock.gif
InBlock.gifexit(
0);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endmain*/
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*includeproducer*/
None.gif
void*
None.gifproduce(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(;;)dot.gif{
InBlock.gifPthread_mutex_lock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(shared.nput>=nitems)dot.gif{//生产完毕
InBlock.gif
Pthread_mutex_unlock(&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
return(NULL);/**//*arrayisfull,we'redone*/
ExpandedSubBlockEnd.gif}

InBlock.gifshared.buff[shared.nput]
=shared.nval;
InBlock.gifshared.nput
++;
InBlock.gifshared.nval
++;
InBlock.gifPthread_mutex_unlock(
&shared.mutex);
InBlock.gif
*((int*)arg)+=1;//每个线程私有的计数器,不需要加锁
ExpandedSubBlockEnd.gif
}

ExpandedBlockEnd.gif}

None.gif
None.gif
void*
None.gifconsume(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nitems;i++)dot.gif{
InBlock.gif
if(shared.buff[i]!=i)
InBlock.gifprintf(
"buff[%d]=%d/n",i,shared.buff[i]);
ExpandedSubBlockEnd.gif}

InBlock.gif
return(NULL);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endproducer*/
None.gif
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


生产者和消费者之间的同步,消费者采用的方式就是不断轮询。

None.gif
None.gif#include
"unpipc.h"
None.gif
None.gif
#defineMAXNITEMS1000000
None.gif
#defineMAXNTHREADS100
None.gif
ExpandedBlockStart.gifContractedBlock.gif
intnitems;/**//*read-onlybyproducerandconsumer*/
ExpandedBlockStart.gifContractedBlock.gif
structdot.gif{
InBlock.gifpthread_mutex_tmutex;
InBlock.gif
intbuff[MAXNITEMS];
InBlock.gif
intnput;
InBlock.gif
intnval;
ExpandedBlockStart.gifContractedBlock.gif}
shared=dot.gif{PTHREAD_MUTEX_INITIALIZER};
None.gif
None.gif
void*produce(void*),*consume(void*);
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*includemain*/
None.gif
int
None.gifmain(
intargc,char**argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti,nthreads,count[MAXNTHREADS];
InBlock.gifpthread_ttid_produce[MAXNTHREADS],tid_consume;
InBlock.gif
InBlock.gif
if(argc!=3)
InBlock.giferr_quit(
"usage:prodcons3<#items><#threads>");
InBlock.gifnitems
=min(atoi(argv[1]),MAXNITEMS);
InBlock.gifnthreads
=min(atoi(argv[2]),MAXNTHREADS);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4createallproducersandoneconsumer*/
InBlock.gifSet_concurrency(nthreads
+1);
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifcount[i]
=0;
InBlock.gifPthread_create(
&tid_produce[i],NULL,produce,&count[i]);
ExpandedSubBlockEnd.gif}

InBlock.gifPthread_create(
&tid_consume,NULL,consume,NULL);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4waitforallproducersandtheconsumer*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifPthread_join(tid_produce[i],NULL);
InBlock.gifprintf(
"count[%d]=%d/n",i,count[i]);
ExpandedSubBlockEnd.gif}

InBlock.gifPthread_join(tid_consume,NULL);
InBlock.gif
InBlock.gifexit(
0);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endmain*/
None.gif
None.gif
void*
None.gifproduce(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(;;)dot.gif{
InBlock.gifPthread_mutex_lock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(shared.nput>=nitems)dot.gif{
InBlock.gifPthread_mutex_unlock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
return(NULL);/**//*arrayisfull,we'redone*/
ExpandedSubBlockEnd.gif}

InBlock.gifshared.buff[shared.nput]
=shared.nval;
InBlock.gifshared.nput
++;
InBlock.gifshared.nval
++;
InBlock.gifPthread_mutex_unlock(
&shared.mutex);
InBlock.gif
*((int*)arg)+=1;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*includeconsume*/
None.gif
void
None.gifconsume_wait(
inti)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(;;)dot.gif{
InBlock.gifPthread_mutex_lock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(i<shared.nput)dot.gif{
InBlock.gifPthread_mutex_unlock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
return;/**//*anitemisready*/
ExpandedSubBlockEnd.gif}

InBlock.gifPthread_mutex_unlock(
&shared.mutex);
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif
void*
None.gifconsume(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nitems;i++)dot.gif{
InBlock.gifconsume_wait(i);
InBlock.gif
if(shared.buff[i]!=i)
InBlock.gifprintf(
"buff[%d]=%d/n",i,shared.buff[i]);
ExpandedSubBlockEnd.gif}

InBlock.gif
return(NULL);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endconsume*/
None.gif

每个条件变量都有一个互斥锁与之关联,调用pthread_cond_wait等待某个条件为真时,同时指定其条件变量的地址和所关联的互斥锁的地址

使用条件变量来通知,避免消费者轮询

ExpandedBlockStart.gifContractedBlock.gif/**//*includeglobals*/
None.gif#include
"unpipc.h"
None.gif
None.gif
#defineMAXNITEMS1000000
None.gif
#defineMAXNTHREADS100
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*globalssharedbythreads*/
ExpandedBlockStart.gifContractedBlock.gif
intnitems;/**//*read-onlybyproducerandconsumer*/
None.gif
intbuff[MAXNITEMS];
ExpandedBlockStart.gifContractedBlock.gif
structdot.gif{//用于生产者之间的同步
InBlock.gif
pthread_mutex_tmutex;
ExpandedSubBlockStart.gifContractedSubBlock.gif
intnput;/**//*nextindextostore*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
intnval;/**//*nextvaluetostore*/
ExpandedBlockStart.gifContractedBlock.gif}
put=dot.gif{PTHREAD_MUTEX_INITIALIZER};
None.gif
ExpandedBlockStart.gifContractedBlock.gif
structdot.gif{//用于生产者和消费者之间同步
InBlock.gif
pthread_mutex_tmutex;
InBlock.gifpthread_cond_tcond;
ExpandedSubBlockStart.gifContractedSubBlock.gif
intnready;/**//*numberreadyforconsumer*/
ExpandedBlockStart.gifContractedBlock.gif}
nready=dot.gif{PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER};
ExpandedBlockStart.gifContractedBlock.gif
/**//*endglobals*/
None.gif
None.gif
void*produce(void*),*consume(void*);
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*includemain*/
None.gif
int
None.gifmain(
intargc,char**argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti,nthreads,count[MAXNTHREADS];
InBlock.gifpthread_ttid_produce[MAXNTHREADS],tid_consume;
InBlock.gif
InBlock.gif
if(argc!=3)
InBlock.giferr_quit(
"usage:prodcons6<#items><#threads>");
InBlock.gifnitems
=min(atoi(argv[1]),MAXNITEMS);
InBlock.gifnthreads
=min(atoi(argv[2]),MAXNTHREADS);
InBlock.gif
InBlock.gifSet_concurrency(nthreads
+1);
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*4createallproducersandoneconsumer*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifcount[i]
=0;
InBlock.gifPthread_create(
&tid_produce[i],NULL,produce,&count[i]);
ExpandedSubBlockEnd.gif}

InBlock.gifPthread_create(
&tid_consume,NULL,consume,NULL);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//*waitforallproducersandtheconsumer*/
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nthreads;i++)dot.gif{
InBlock.gifPthread_join(tid_produce[i],NULL);
InBlock.gifprintf(
"count[%d]=%d/n",i,count[i]);
ExpandedSubBlockEnd.gif}

InBlock.gifPthread_join(tid_consume,NULL);
InBlock.gif
InBlock.gifexit(
0);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endmain*/
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//*includeprodcons*/
None.gif
void*
None.gifproduce(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(;;)dot.gif{
InBlock.gifPthread_mutex_lock(
&put.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(put.nput>=nitems)dot.gif{
InBlock.gifPthread_mutex_unlock(
&put.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif
return(NULL);/**//*arrayisfull,we'redone*/
ExpandedSubBlockEnd.gif}

InBlock.gifbuff[put.nput]
=put.nval;
InBlock.gifput.nput
++;
InBlock.gifput.nval
++;
InBlock.gifPthread_mutex_unlock(
&put.mutex);
InBlock.gif
InBlock.gifPthread_mutex_lock(
&nready.mutex);
InBlock.gif
if(nready.nready==0)
InBlock.gifPthread_cond_signal(
&nready.cond);//发出信号唤醒消费者
InBlock.gif
nready.nready++;//置为1
InBlock.gif
Pthread_mutex_unlock(&nready.mutex);
InBlock.gif
InBlock.gif
*((int*)arg)+=1;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif
void*
None.gifconsume(
void*arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
inti;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
for(i=0;i<nitems;i++)dot.gif{
InBlock.gifPthread_mutex_lock(
&nready.mutex);
InBlock.gif
while(nready.nready==0)
InBlock.gifPthread_cond_wait(
&nready.cond,&nready.mutex);//wait条件变量
InBlock.gif
nready.nready--;//置为0
InBlock.gif
Pthread_mutex_unlock(&nready.mutex);
InBlock.gif
InBlock.gif
if(buff[i]!=i)
InBlock.gifprintf(
"buff[%d]=%d/n",i,buff[i]);
ExpandedSubBlockEnd.gif}

InBlock.gif
return(NULL);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**//*endprodcons*/
None.gif
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页