问题描述
三个烟鬼问题实际上就是线程的并发问题:
- 三个烟鬼,一个有烟草,一个有烟纸,一个有火柴
- 上帝拿走两个人的材料给一个人,那么你那个人可以抽一支烟
- 当那个人抽完这只烟的时候,上帝重新做决策
题目分析:
-其实就是有前提条件的同步问题:
- “上帝给材料才能抽烟”
- “当前抽烟的抽完上帝才能指派下一个人”
- 同时只会有一个人在抽烟
基本思路:
- 首先考虑上帝:
- 上帝指派人的时候,不能有人在抽烟,所以需要一个信号量标记是否有人在抽烟:
- 1代表当前没有人正在抽烟
- 0代表当前有人正在抽烟
- 上帝指派之后会更新一个烟鬼的信号量使它可以抽烟,然后上帝等待烟鬼抽完烟再进行重新指派
- 上帝指派人的时候,不能有人在抽烟,所以需要一个信号量标记是否有人在抽烟:
- 烟鬼要等待上帝指派,才能抽烟,所以每个烟鬼有一个信号量
- 1代表当前有权利抽烟
- 0代表还需继续等待
- 抽完烟更新smoking状态唤醒上帝
代码如下:
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define TRUE 1
#define MAX 3
#define p(x) sem_wait(&x)
#define v(x) sem_post(&x)
sem_t smoker[MAX],smoking;
void init ( )
{
int i;
for ( i = 0 ; i < MAX ; i++ )
sem_init ( &smoker[i] , 0 , 0 );
sem_init ( &smoking , 0 , 1 );
}
void* _judge ( )
{
while ( TRUE )
{
p(smoking);
int x = (rand()%MAX+MAX)%MAX;
v(smoker[x]);
}
}
void* _smoker ( void* arg )
{
int *p = (int*)arg;
int x = *p;
while ( TRUE )
{
p(smoker[x]);
printf ( "%dth smoker smoking....\n" , x );
sleep(1);
v(smoking);
}
}
int main ( )
{
init ( );
pthread_t sid[MAX],jid;
int sid1[MAX];
int i;
srand ( (unsigned)time(NULL));
pthread_create ( &jid , NULL , _judge , NULL );
for ( i = 0 ; i < MAX; i++ )
{
sid1[i] = i;
pthread_create ( &sid[i] , NULL , _smoker , &sid1[i] );
}
for ( i = 0 ; i < MAX ; i++ )
pthread_join ( sid[i] , NULL );
}