linux 生产者 消费者 问题

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


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

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>


#define NBUFF 10 // 缓冲区大小

#define SEM_MUTEX "mutex" 
#define SEM_NEMPTY "nempty" 
#define SEM_NSTORED "nstored" 

static int nitems = NBUFF;

struct _shared
{
        int buff[ NBUFF ]; // 缓冲区大小
        sem_t* mutex;  // 访问缓冲区的互斥锁
        sem_t* nempty; // 当前空闲的缓冲区个数
        sem_t* nstored; // 当前缓冲区可用个数
} shared; // 线程共享量

void* producer( void* );
void* consumer( void* );

int main( int argc, char** argv )
{
        pthread_t tid_producer, tid_consumer;
        memset( shared.buff, 0, sizeof( shared.buff ) );
        shared.mutex = sem_open( SEM_MUTEX, O_CREAT | O_EXCL, 0644, 1 );
        shared.nempty = sem_open( SEM_NEMPTY, O_CREAT | O_EXCL, 0644, NBUFF );
        shared.nstored = sem_open( SEM_NSTORED, O_CREAT | O_EXCL, 0644, 0 );

        pthread_setconcurrency( 2 );

        // create producer and consumer
        pthread_create( &tid_producer, NULL, producer, NULL );
        pthread_create( &tid_consumer, NULL, consumer, NULL );

        // wait for two threads
        pthread_join( tid_producer, NULL );
        pthread_join( tid_consumer, NULL );

        // remove semaphores
        sem_unlink( SEM_MUTEX );
        sem_unlink( SEM_NEMPTY );
        sem_unlink( SEM_NSTORED );

        return 0;
}

void* producer( void* arg )
{
        int i ;
        for ( i = 0; i < nitems; i++ )
        {
                sem_wait( shared.nempty ); // P( nempty )
                sem_wait( shared.mutex );  // P( mutex )

                shared.buff[ i % NBUFF ] = i;
                printf( "producer: %d\n", shared.buff[ i % NBUFF ] );

                sem_post( shared.mutex ); // V( mutex )
                sem_post( shared.nstored ); // V( nstored )

                sleep( 1 ); // 暂停,唤醒consumer
        }

        return ( void* )0;
}

void* consumer( void* arg )
{
        int i;
        for ( i = 0; i < nitems; i++ )
        {
                sem_wait( shared.nstored ); // P( nstored )
                sem_wait( shared.mutex );  // P( mutex )

                printf( "consumer: buff[%d] = %d\n", i, shared.buff[ i % NBUFF ] );

                sem_post( shared.mutex ); // V( mutex )
                sem_post( shared.nempty );  // V( empty )

                sleep( 2 ); // 暂停,唤醒producer
        }

        return ( void* )0;
}

// 编译

kennie@cbib:~/pthreadDIR$ g++ -lpthread -o producer_consumer.out producer_consumer.cpp

// 运行结果

producer: 0
consumer: buff[0] = 0
producer: 1
consumer: buff[1] = 1
producer: 2
producer: 3
consumer: buff[2] = 2
producer: 4
producer: 5
consumer: buff[3] = 3
producer: 6
producer: 7
consumer: buff[4] = 4
producer: 8
producer: 9
consumer: buff[5] = 5
consumer: buff[6] = 6
consumer: buff[7] = 7
consumer: buff[8] = 8
consumer: buff[9] = 9

参考 《Unix网络编程 卷2 进程通信》 第10章 Posix信号量 10.6 生产者-消费者问题




  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值