以生产者/消费者模型为依据,在linux环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
模拟实现的情景
*M生产者,N消费者, K缓冲区
*解决生产者消费者的同步问题,访问缓冲区的互斥问题
*生产者放产品位置递增;消费者要寻找有产品的位置,不采用位置自增,解决速度不一致的问题.
*缓冲区在某一时刻只有一个线程访问
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> /*一些说明*/ #define P( S ) sem_wait( S ) /* P操作 对应库函数 */ #define V( S ) sem_post( S ) /* V操作 对应库函数 */ #define LOCK( S ) pthread_mutex_lock( S ) /* 锁定临界区 */ #define UNLOCK( S ) pthread_mutex_unlock( S ) /* 解锁临界区 */ /*变量定义*/ #define M 2 /* 生产者数目 */ #define N 3 /* 消费者数目 */ #define K 10 /* 缓冲数目 */ #define producter_speed 2 #define consumer_speed 1 int in; /* 生产者放产品的位置 */ int out; /* 消费者取产品的位置 */ int buff[K] = { 0 }; /* 缓冲初始化为0,表示开始时没有产品 */ sem_t empty_sem; /*同步信号量,有空位置就放 */ sem_t full_sem; /*同步信号量,有产品就取 */ pthread_mutex_t mutex; /* 互斥信号量 */ int producter_id= 0; /* 生产者id */ int consumer_id = 0; /* 消费者id */ /*打印缓冲区*/ void printBuff() { int i; for ( i = 0; i < K; i++ ) printf( "%d ", buff[i] ); printf( " " ); } /*寻找有产品的位置*/ int find_position() { int i; for ( i = 0; i < K; i++ ) { if ( buff[i] == 1 ) return(i); } } /*生产者*/ void *producter() { int id = producter_id++; while ( 1 ) { /* 用sleep的数量可以调节生产和消费的速度 */ sleep( producter_speed ); P( &empty_sem ); LOCK( &mutex ); in = in % K; printf( "%d号生产者在%d位置放产品: ", id, in ); buff[in] = 1; printBuff(); in++; UNLOCK( &mutex ); V( &full_sem ); } } /*消费者*/ void *consumer() { int id = consumer_id++; while ( 1 ) { sleep( consumer_speed ); P( &full_sem ); LOCK( &mutex ); out = find_position(); printf( "%d号消费者在%d位置取产品: ", id, out ); buff[out] = 0; printBuff(); UNLOCK( &mutex ); V( &empty_sem ); } } int main() { pthread_t p_id[M]; pthread_t c_id[N]; int i; int ret[N]; /* 初始化同步信号量 */ int ini1 = sem_init( &empty_sem, 0, M ); int ini2 = sem_init( &full_sem, 0, 0 ); /* 初始化互斥信号量 */ int ini3 = pthread_mutex_init( &mutex, NULL ); if ( ini1 != 0 && ini2 != 0 && ini3 != 0 ) { printf( "信号量初始化失败 " ); exit( 1 ); } /* 创建M个生产者线程 */ for ( i = 0; i < M; i++ ) { ret[i] = pthread_create( &p_id[i], NULL, producter, (void *) (&i) ); if ( ret[i] != 0 ) { printf( "%d号生产者创建失败 ", i ); exit( 1 ); } } /* 创建N个消费者线程 */ for ( i = 0; i < N; i++ ) { ret[i] = pthread_create( &c_id[i], NULL, consumer, NULL ); if ( ret[i] != 0 ) { printf( "%d号消费者创建失败 ", i ); exit( 1 ); } } /*启动线程*/ for ( i = 0; i < N; i++ ) { pthread_join( p_id[i], NULL ); pthread_join( c_id[i], NULL ); } return(0); }