理发师多线程实现----面包师多进程实现

理发师问题的实现,多线程。

Linux 理发师、面包师程序文档

理发师问题

有一个理发师,一把理发椅和4把供等候理发的顾客坐的椅子。如果没有顾客,则理发师便在理发师椅子上睡觉;当一个顾客到来时,必须唤醒理发师进行理发;如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,他就坐下来等,如果没有空椅子,他就离开。为理发师和顾客各编一段程序实现他们的行为。使用线程实现

初始化:顾客数为0,表示还没有顾客过来;理发师为0,表示理发师在睡觉;互斥信号量,用于控制临界区,防止同时修改waiting 值;椅子数为4,表示最多有4个顾客等待。

创建一个理发师线程,创建10个顾客进程,每次经过随机事件创建一个

程序流程图

代码:

 

#include <stdio.h>

#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <math.h>
#define CHAIRS 4


sem_t customers;//等待服务的顾客数
sem_t barbers;//等待顾客的理发师数
pthread_mutex_t mutex;//用于互斥
int waiting = 0;//等待的顾客
int if_no_more = 0;
void cut_hair()
{
printf("理发师:开始理发\n");
sleep(rand()%7 + 1);
}


void* barber()
{
    while(1)
    {
    if(waiting == 0)
    printf("理发师:当前没有顾客,睡觉\n");
        sem_wait(&customers);//如果没有顾客,理发师睡,进程阻塞
        pthread_mutex_lock(&mutex);//互斥进入临界区,欲修改waiting
        waiting--;//等待理发人数减一
        pthread_mutex_unlock( &mutex);//退出临界区,完成对waiting的修改
        cut_hair();//理发师理发
        sem_post(&barbers);//理发师结束理发barbers++
        sleep(rand()%2 + 1);
        if(if_no_more && waiting == 0)
        break;
    }
    sleep(3);
    printf("下班\n");
    return;
}
void* customer()
{
int color = rand()%5+32;
#define START "\033[1;%dm"
#define END "\033[0m"
    pthread_mutex_lock(&mutex);//互斥进入临界区,欲修改waiting
    if(waiting<CHAIRS)//如果有空椅子
    {
        waiting++;//等待理发的人数加1
        printf(START"新加了一位顾客%d\t等待理发人数:%d\n"END,color, (unsigned int)pthread_self(),waiting);
        pthread_mutex_unlock( &mutex);//退出临界区,完成对waiting的修改
        sem_post(&customers);//等待理发的人数加1,如有必要,唤醒理发师
        sem_wait(&barbers);//理发师是否空闲,若忙则阻塞barbers--
        printf(START"\t%d说:谢谢理发师。\n"END,color,(unsigned int)pthread_self());
    }
    else 
    {
    printf(START"%d说:没有空椅子了,我换一家\n"END,31,(unsigned int)pthread_self());
    pthread_mutex_unlock( &mutex);//没有空椅子,顾客离开
    }
    return;
}
int main()
{
int i;
pthread_t barber_id, customer_id;
sem_init(&customers, 0, 0);
    sem_init(&barbers, 0, 0);  
    pthread_mutex_init( &mutex, NULL);
    srand(time(0));
    pthread_create( &barber_id, NULL, barber, NULL);
    
    for(i=0; i<10;i++)
    {
    sleep(rand()%4 + 1);  
        pthread_create( &customer_id, NULL, customer, NULL); 
    }


    if_no_more = 1;//后面没有客户了
    pthread_join(barber_id,NULL);
    return 0;


 

}

运行显示介绍

gcc ***.c -oxx -lpthread 编译

理发师:当没有顾客时,理发师睡觉

        当有顾客时,理发师为一位顾客理发,等待理发的人数减1。

        当不在有顾客来时,并且没有顾客在等待,理发师下班

顾客:  当有空椅子时:新加了一位顾客,等待理发的人数加1.

        当没有空椅子时:没有空椅子了,我换一家。

运行结果

 

面包师问题:

面包师有很多面包和蛋糕,由 3 个销售人员销售。每个顾客进店后先取一个号,并且等着叫号。当一个销售人员空闲下来,就叫下一个号。请分别编写销售人员和顾客进程的程序。

 

使用多进程实现:

创建2个共用的信号量,waiting和free,waiting 初始值为3表示有3个售货员,free初始值为0表示初始没有顾客在等待。

 

:创建了三个销售人员进程来为顾客服务。

  销售人员进程减少waiting的人数,在进程执行过程中,free人数会先减一,在为顾客服务完之后,free人数加一。

:一个顾客进程。

  顾客进程增加waiting的人数

 

程序流程图:

代码:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define START "\033[1;%dm"
#define END "\033[0m"
#define MYKEY 2//制定信号灯集的标志

union semun
{
    int val; 
    struct semid_ds *buf;
    unsigned short int *array;
    struct seminfo *__buf;
}sem1,sem2;

int semaphore_create();
int output_semaphore(int sid);
int up_num_of_waiting(int sid);
int down_num_of_waiting(int sid);
int up_num_of_free(int sid);
int down_num_of_free(int sid);

//创建信号集,并返回信号灯集描述字
int semaphore_create()
{
    return semget(MYKEY, 2, IPC_CREAT);//key标识一个信号灯集,2表示创建2个信号量
}
//输出对应信号集中信号的数量
int output_semaphore(int sid)
{
    printf("num of waiting: %d\n", semctl(sid, 0, GETVAL,sem1));//0信号量表示等待的人数
    printf("num of free   : %d\n", semctl(sid, 1, GETVAL,sem2));//1信号量表示空闲的服务员人数
}

int up_num_of_waiting(int sid)
{
    /*
    struct sembuf {  
    unsigned short  sem_num; // 对应信号集中的信号灯   
    short      sem_op;       // 对信号灯的操作   
    short      sem_flg;      // 操作标志   
    };
    */
    struct sembuf operation = {0, 1, SEM_UNDO};//等待人数加1
    return semop(sid, &operation, 1);
}

int down_num_of_waiting(int sid)
{
    struct sembuf operation = {0, -1, SEM_UNDO};//等待人数减一
    return semop(sid, &operation, 1);
}

int up_num_of_free(int sid)
{
    struct sembuf operation = {1, 1, SEM_UNDO};//空闲服务员人数加1
    return semop(sid, &operation, 1);
}

int down_num_of_free(int sid)
{
    struct sembuf operation = {1, -1, SEM_UNDO};//空闲服务员人数减1
    return semop(sid, &operation, 1);
}

void customer()
{
    int color = 34;
    int sid = semaphore_create();
    while(1)
    {
        up_num_of_waiting(sid);
        printf("########顾客区########\n");
        printf(START"一位顾客到了\n"END,color);
        printf(START"num of waiting: %d\n"END, color,semctl(sid, 0, GETVAL,sem1));
        printf(START"num of free: %d\n"END, color,semctl(sid, 1, GETVAL,sem2));
        //output_semaphore(sid);        
        printf("######################\n");
        //sleep(0.5); 
        //output_semaphore(sid);
        //sleep(0.5);
        //down_num_of_free(sid);
        //output_semaphore(sid);
        //printf(START"一个销售人员空闲,并为顾客服务 \n"END,color);
        sleep(rand()%2 + 1);
        //up_num_of_free(sid);
    }    
}

void salesman()
{
    int color = 33;
    int pid = getpid();
    int sid = semaphore_create();
    while(1)
    {
        down_num_of_waiting(sid);
        //sleep(1);
        down_num_of_free(sid);
        printf("********销售区********\n");   
        printf(START"销售员%d: 为顾客提供服务,空闲人数减一,等待人数减一\n"END,color,pid);
        //printf(START"num of waiting: %d\n"END, color,semctl(sid, 0, GETVAL,sem1));
        //printf(START"num of free: %d\n"END, color,semctl(sid, 1, GETVAL,sem2));
        //output_semaphore(sid);
        printf("*********************\n");
        sleep(rand()%10 + 1);  
        up_num_of_free(sid);
    }

}
//将所有信号量置初始值
void init()
{
    int sid = semaphore_create();
    sem1.val = 0;
    sem2.val = 3;
    semctl(sid, 0, SETVAL, sem1);
    semctl(sid, 1, SETVAL, sem2);
        
}
int main()
{
    init();
    pid_t sale1,sale2,sale3;
    srand(time(0));
    sale1 = fork();
    if(sale1 == 0 )
    {
        salesman();
    }
    sale2 = fork();
    if(sale2 == 0 )
    {
        salesman();
    }
    sale3 = fork();
    if(sale3 == 0 )
    {
        salesman();
    }
    else
    {
        customer();
    }
    return 0;
}

运行显示介绍:

顾客进程输出:

########顾客区########

一位顾客到了

num of waiting: x

num of free: x

######################

售货员进程输出:

********销售区********

销售员xx:为顾客提供服务,空闲人数减一,等待人数减一

**********************

因为进程可以同时输出,所以会交叉输出,因此设置了界限,这样在看程序输出时,通过界限及不同进程的输出语句,可以较清晰地看到结果

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值