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

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

None.gif #include     " unpipc.h "
None.gif
None.gif
#define     MAXNITEMS         1000000
None.gif
#define     MAXNTHREADS            100
None.gif
ExpandedBlockStart.gifContractedBlock.gif
int         nitems;             /**/ /* read-only by producer and consumer */
ExpandedBlockStart.gifContractedBlock.gif
struct   dot.gif {
InBlock.gif  pthread_mutex_t    mutex;  
//互斥信号量
InBlock.gif
  int    buff[MAXNITEMS];
InBlock.gif  
int    nput;//下一个存放元素的下标
InBlock.gif
  int    nval;//下一个存放的值
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(
int  argc,  char   ** argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int            i, nthreads, count[MAXNTHREADS];
InBlock.gif    pthread_t    tid_produce[MAXNTHREADS], tid_consume;
InBlock.gif
InBlock.gif    
if (argc != 3)
InBlock.gif        err_quit(
"usage: prodcons2 <#items> <#threads>");
InBlock.gif    nitems 
= min(atoi(argv[1]), MAXNITEMS);//生产者存放的条目数
InBlock.gif
    nthreads = min(atoi(argv[2]), MAXNTHREADS);//待创建的生产者线程数
InBlock.gif

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

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

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

ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end main */
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* include producer */
None.gif
void   *
None.gifproduce(
void   * arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for ( ; ; ) dot.gif{
InBlock.gif        Pthread_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);        /**//* array is full, we're done */
ExpandedSubBlockEnd.gif        }

InBlock.gif        shared.buff[shared.nput] 
= shared.nval;
InBlock.gif        shared.nput
++;
InBlock.gif        shared.nval
++;
InBlock.gif        Pthread_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    
int        i;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nitems; i++dot.gif{
InBlock.gif        
if (shared.buff[i] != i)
InBlock.gif            printf(
"buff[%d] = %d\n", i, shared.buff[i]);
ExpandedSubBlockEnd.gif    }

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

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


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

None.gif
None.gif#include    
" unpipc.h "
None.gif
None.gif
#define     MAXNITEMS         1000000
None.gif
#define     MAXNTHREADS            100
None.gif
ExpandedBlockStart.gifContractedBlock.gif
int         nitems;             /**/ /* read-only by producer and consumer */
ExpandedBlockStart.gifContractedBlock.gif
struct   dot.gif {
InBlock.gif  pthread_mutex_t    mutex;
InBlock.gif  
int    buff[MAXNITEMS];
InBlock.gif  
int    nput;
InBlock.gif  
int    nval;
ExpandedBlockStart.gifContractedBlock.gif}
 shared  =   dot.gif { PTHREAD_MUTEX_INITIALIZER } ;
None.gif
None.gif
void      * produce( void   * ),  * consume( void   * );
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* include main */
None.gif
int
None.gifmain(
int  argc,  char   ** argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int            i, nthreads, count[MAXNTHREADS];
InBlock.gif    pthread_t    tid_produce[MAXNTHREADS], tid_consume;
InBlock.gif
InBlock.gif    
if (argc != 3)
InBlock.gif        err_quit(
"usage: prodcons3 <#items> <#threads>");
InBlock.gif    nitems 
= min(atoi(argv[1]), MAXNITEMS);
InBlock.gif    nthreads 
= min(atoi(argv[2]), MAXNTHREADS);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//* 4create all producers and one consumer */
InBlock.gif    Set_concurrency(nthreads 
+ 1);
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nthreads; i++dot.gif{
InBlock.gif        count[i] 
= 0;
InBlock.gif        Pthread_create(
&tid_produce[i], NULL, produce, &count[i]);
ExpandedSubBlockEnd.gif    }

InBlock.gif    Pthread_create(
&tid_consume, NULL, consume, NULL);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//* 4wait for all producers and the consumer */
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nthreads; i++dot.gif{
InBlock.gif        Pthread_join(tid_produce[i], NULL);
InBlock.gif        printf(
"count[%d] = %d\n", i, count[i]);    
ExpandedSubBlockEnd.gif    }

InBlock.gif    Pthread_join(tid_consume, NULL);
InBlock.gif
InBlock.gif    exit(
0);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end main */
None.gif
None.gif
void   *
None.gifproduce(
void   * arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for ( ; ; ) dot.gif{
InBlock.gif        Pthread_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);        /**//* array is full, we're done */
ExpandedSubBlockEnd.gif        }

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

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* include consume */
None.gif
void
None.gifconsume_wait(
int  i)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for ( ; ; ) dot.gif{
InBlock.gif        Pthread_mutex_lock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (i < shared.nput) dot.gif{
InBlock.gif            Pthread_mutex_unlock(
&shared.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif            
return;            /**//* an item is ready */
ExpandedSubBlockEnd.gif        }

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

ExpandedBlockEnd.gif}

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

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

ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end consume */
None.gif

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

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

ExpandedBlockStart.gif ContractedBlock.gif /**/ /* include globals */
None.gif#include    
" unpipc.h "
None.gif
None.gif
#define     MAXNITEMS         1000000
None.gif
#define     MAXNTHREADS            100
None.gif
ExpandedBlockStart.gifContractedBlock.gif        
/**/ /* globals shared by threads */
ExpandedBlockStart.gifContractedBlock.gif
int         nitems;                 /**/ /* read-only by producer and consumer */
None.gif
int         buff[MAXNITEMS];
ExpandedBlockStart.gifContractedBlock.gif
struct   dot.gif {//用于生产者之间的同步
InBlock.gif
  pthread_mutex_t    mutex;
ExpandedSubBlockStart.gifContractedSubBlock.gif  
int                nput;    /**//* next index to store */
ExpandedSubBlockStart.gifContractedSubBlock.gif  
int                nval;    /**//* next value to store */
ExpandedBlockStart.gifContractedBlock.gif}
 put  =   dot.gif { PTHREAD_MUTEX_INITIALIZER } ;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
struct   dot.gif {//用于生产者和消费者之间同步
InBlock.gif
  pthread_mutex_t    mutex;
InBlock.gif  pthread_cond_t    cond;
ExpandedSubBlockStart.gifContractedSubBlock.gif  
int                nready;    /**//* number ready for consumer */
ExpandedBlockStart.gifContractedBlock.gif}
 nready  =   dot.gif { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER } ;
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end globals */
None.gif
None.gif
void      * produce( void   * ),  * consume( void   * );
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* include main */
None.gif
int
None.gifmain(
int  argc,  char   ** argv)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int            i, nthreads, count[MAXNTHREADS];
InBlock.gif    pthread_t    tid_produce[MAXNTHREADS], tid_consume;
InBlock.gif
InBlock.gif    
if (argc != 3)
InBlock.gif        err_quit(
"usage: prodcons6 <#items> <#threads>");
InBlock.gif    nitems 
= min(atoi(argv[1]), MAXNITEMS);
InBlock.gif    nthreads 
= min(atoi(argv[2]), MAXNTHREADS);
InBlock.gif
InBlock.gif    Set_concurrency(nthreads 
+ 1);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//* 4create all producers and one consumer */
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nthreads; i++dot.gif{
InBlock.gif        count[i] 
= 0;
InBlock.gif        Pthread_create(
&tid_produce[i], NULL, produce, &count[i]);
ExpandedSubBlockEnd.gif    }

InBlock.gif    Pthread_create(
&tid_consume, NULL, consume, NULL);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//* wait for all producers and the consumer */
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nthreads; i++dot.gif{
InBlock.gif        Pthread_join(tid_produce[i], NULL);
InBlock.gif        printf(
"count[%d] = %d\n", i, count[i]);    
ExpandedSubBlockEnd.gif    }

InBlock.gif    Pthread_join(tid_consume, NULL);
InBlock.gif
InBlock.gif    exit(
0);
ExpandedBlockEnd.gif}

ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end main */
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**/ /* include prodcons */
None.gif
void   *
None.gifproduce(
void   * arg)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for ( ; ; ) dot.gif{
InBlock.gif        Pthread_mutex_lock(
&put.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (put.nput >= nitems) dot.gif{
InBlock.gif            Pthread_mutex_unlock(
&put.mutex);
ExpandedSubBlockStart.gifContractedSubBlock.gif            
return(NULL);        /**//* array is full, we're done */
ExpandedSubBlockEnd.gif        }

InBlock.gif        buff[put.nput] 
= put.nval;
InBlock.gif        put.nput
++;
InBlock.gif        put.nval
++;
InBlock.gif        Pthread_mutex_unlock(
&put.mutex);
InBlock.gif
InBlock.gif        Pthread_mutex_lock(
&nready.mutex);
InBlock.gif        
if (nready.nready == 0)
InBlock.gif            Pthread_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    
int        i;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for (i = 0; i < nitems; i++dot.gif{
InBlock.gif        Pthread_mutex_lock(
&nready.mutex);
InBlock.gif        
while (nready.nready == 0)
InBlock.gif            Pthread_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.gif            printf(
"buff[%d] = %d\n", i, buff[i]);
ExpandedSubBlockEnd.gif    }

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

ExpandedBlockStart.gifContractedBlock.gif
/**/ /* end prodcons */
None.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值