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

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


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

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.gifContractedBlock.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