以生产者/消费者模型为依据,在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( "\n" );
}
/*寻找有产品的位置*/
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位置放产品: \t", 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位置取产品: \t", 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( "信号量初始化失败 \n" );
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号生产者创建失败\n", 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号消费者创建失败\n", i );
exit( 1 );
}
}
/*启动线程*/
for ( i = 0; i < N; i++ )
{
pthread_join( p_id[i], NULL );
pthread_join( c_id[i], NULL );
}
return(0);
}