生产者-消费者问题

来源:互联网 发布:数控螺纹g76编程格式 编辑:程序博客网 时间:2024/05/16 07:21

 生产者-消费者是很有意思的一种算法。它的存在主要是两个目的,第一就是满足生产者对资源的不断创造;第二就是满足消费者对资源的不断索取。当然,因为空间是有限的,所以资源既不能无限存储,也不能无限索取。

 

生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。 


以下linux程序展示的是一个生产者和一个消费者共享一个NBUFF大小的缓冲区进行同步的演示

[cpp] view plaincopyprint?
  1. #include<stdio.h>   
  2. #include<string.h>   
  3. #include<pthread.h>   
  4. #include<unistd.h>   
  5. #include<semaphore.h>   
  6. #include<fcntl.h>   
  7. #include<sys/stat.h>   
  8.   
  9.   
  10. #define NBUFF 10 // 缓冲区大小   
  11.   
  12. #define SEM_MUTEX "mutex"    
  13. #define SEM_NEMPTY "nempty"   
  14. #define SEM_NSTORED "nstored"    
  15.   
  16. static int nitems = NBUFF;  
  17.   
  18. struct _shared  
  19. {  
  20.         int buff[ NBUFF ]; // 缓冲区大小  
  21.         sem_t* mutex;  // 访问缓冲区的互斥锁  
  22.         sem_t* nempty; // 当前空闲的缓冲区个数   
  23.         sem_t* nstored; // 当前缓冲区可用个数  
  24. } shared; // 线程共享量   
  25.   
  26. void* producer( void* );  
  27. void* consumer( void* );  
  28.   
  29. int main( int argc, char** argv )  
  30. {  
  31.         pthread_t tid_producer, tid_consumer;  
  32.         memset( shared.buff, 0, sizeof( shared.buff ) );  
  33.         shared.mutex = sem_open( SEM_MUTEX, O_CREAT | O_EXCL, 0644, 1 );  
  34.         shared.nempty = sem_open( SEM_NEMPTY, O_CREAT | O_EXCL, 0644, NBUFF );  
  35.         shared.nstored = sem_open( SEM_NSTORED, O_CREAT | O_EXCL, 0644, 0 );  
  36.   
  37.         pthread_setconcurrency( 2 );  
  38.   
  39.         // create producer and consumer  
  40.         pthread_create( &tid_producer, NULL, producer, NULL );  
  41.         pthread_create( &tid_consumer, NULL, consumer, NULL );  
  42.   
  43.         // wait for two threads  
  44.         pthread_join( tid_producer, NULL );  
  45.         pthread_join( tid_consumer, NULL );  
  46.   
  47.         // remove semaphores   
  48.         sem_unlink( SEM_MUTEX );  
  49.         sem_unlink( SEM_NEMPTY );  
  50.         sem_unlink( SEM_NSTORED );  
  51.   
  52.         return 0;  
  53. }  
  54.   
  55. void* producer( void* arg )  
  56. {  
  57.         int i ;  
  58.         for ( i = 0; i < nitems; i++ )  
  59.         {  
  60.                 sem_wait( shared.nempty ); // P( nempty )  
  61.                 sem_wait( shared.mutex );  // P( mutex )  
  62.   
  63.                 shared.buff[ i % NBUFF ] = i;  
  64.                 printf( "producer: %d\n", shared.buff[ i % NBUFF ] );  
  65.   
  66.                 sem_post( shared.mutex ); // V( mutex )  
  67.                 sem_post( shared.nstored ); // V( nstored )  
  68.   
  69.                 sleep( 1 ); // 暂停,唤醒consumer  
  70.         }  
  71.   
  72.         return ( void* )0;  
  73. }  
  74.   
  75. void* consumer( void* arg )  
  76. {  
  77.         int i;  
  78.         for ( i = 0; i < nitems; i++ )  
  79.         {  
  80.                 sem_wait( shared.nstored ); // P( nstored )  
  81.                 sem_wait( shared.mutex );  // P( mutex )  
  82.   
  83.                 printf( "consumer: buff[%d] = %d\n", i, shared.buff[ i % NBUFF ] );  
  84.   
  85.                 sem_post( shared.mutex ); // V( mutex )  
  86.                 sem_post( shared.nempty );  // V( empty )  
  87.   
  88.                 sleep( 2 ); // 暂停,唤醒producer  
  89.         }  
  90.   
  91.         return ( void* )0;  
  92. }  


// 编译

[cpp] view plaincopyprint?
  1. kennie@cbib:~/pthreadDIR$ g++ -lpthread -o producer_consumer.out producer_consumer.cpp  


// 运行结果

[cpp] view plaincopyprint?
  1. producer: 0  
  2. consumer: buff[0] = 0  
  3. producer: 1  
  4. consumer: buff[1] = 1  
  5. producer: 2  
  6. producer: 3  
  7. consumer: buff[2] = 2  
  8. producer: 4  
  9. producer: 5  
  10. consumer: buff[3] = 3  
  11. producer: 6  
  12. producer: 7  
  13. consumer: buff[4] = 4  
  14. producer: 8  
  15. producer: 9  
  16. consumer: buff[5] = 5  
  17. consumer: buff[6] = 6  
  18. consumer: buff[7] = 7  
  19. consumer: buff[8] = 8  
  20. consumer: buff[9] = 9  


 

原创粉丝点击