进程(线程)间同步互斥问题(四) 三个烟鬼问题

本文深入探讨了并发问题及线程同步机制,通过三个烟鬼的故事,形象地展示了同步问题的基本概念。文章详细介绍了如何使用信号量实现同步,以及在多线程环境下如何确保资源的有效分配和利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述


三个烟鬼问题实际上就是线程的并发问题:

  • 三个烟鬼,一个有烟草,一个有烟纸,一个有火柴
  • 上帝拿走两个人的材料给一个人,那么你那个人可以抽一支烟
  • 当那个人抽完这只烟的时候,上帝重新做决策

题目分析:


-其实就是有前提条件的同步问题:

  • “上帝给材料才能抽烟”
  • “当前抽烟的抽完上帝才能指派下一个人”
  • 同时只会有一个人在抽烟

基本思路:


  • 首先考虑上帝:
    • 上帝指派人的时候,不能有人在抽烟,所以需要一个信号量标记是否有人在抽烟:
      • 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 );
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值