您的位置:首页 > 编程语言 > C语言/C++

多线程 冰淇淋店问题的实现

2015-01-27 21:00 288 查看
【问题描述】

在一个冰淇淋店中 主要有老板,店员,收银员,以及顾客四个角色。用多线程来模拟他们之间的交互关系。

主要流程:

10个顾客到冰淇淋店买冰淇淋,每个顾客需要买1到4个冰淇淋,对每个冰淇淋,指派一名店员来制作。

店里最多有5位店员制作冰淇淋。顾客等候购买数量的冰淇淋制作完成后,到收银台取号,排队,结帐。

店员完成每一个冰淇淋,都要先到老板办公室交给老板审核,如果审核不通过,则重做,审核通过再交给顾客。

交互约束:

1.老板办公室最多只能一个店员进入,不可同时进入两个店员。

2.老板对顾客需求的所有冰淇淋审核完成后才能离开。

3.顾客拿到冰淇淋到收银员那去排队交钱时,必须满足FIFO。

4.只有5位店员可以同时工作。

分析及实现:

主函数:作为老板的角色,安排一天的工作。创建10个顾客线程,并且监视整个生产过程。

顾客线程:创建店员线程,并且模拟产生所需数量的冰淇淋。

店员线程:TotalNeeds个冰淇淋的制作,并且与老板进行交互通信,实现成品的检验。

【PV原语】

(略)

【代码(VC6.0 Console Application)】

#include <stdlib.h>

#include <windows.h>

#include <pthread.h>

#include <semaphore.h>

#pragma comment(lib, "pthreadVC2.lib")

#define NUM_CUSTOM 10            // 设定顾客人数

#define NUM_CLERK   5            // 设定店员人数

void *Clerk(void *clerkDone); // void Clerk(Semosphere clerkDone)

void *Customer(void *numIceCream); // void Customer(int numIceCream)

void *Cashier(void *arg); // void cashier()

void plan(int TotalNeeds);

void progress(bool passed, int numChecked, int numCheckedAndPassed, int TotalNeeds);

void MakeIceCream();

void WalkToCashier(int tid, int numIceCream, int n);

void CashOut(int i);

int IceNum[NUM_CUSTOM];            // 每位顾客购买的数量

pthread_t cuThread[NUM_CUSTOM];

pthread_t maThread;

pthread_t caThread;

sem_t capacity;                    //     (5)    店员

struct    //店员用

{

    bool  passed;                // (false)    用于店员得到老板审核结果

    sem_t requested;            // (0)        用于老板等待店员请求

    sem_t finished;                // (0)        用于店员等待老板审核完成

    sem_t locked;                // (1)        用于实现店员对老板办公室的访问互斥

}inspect;

struct    //收银员用

{

    int number;                    // (0)        顾客排队号码

    sem_t numLock;                // (1)        number互斥锁

    sem_t requested;            // (0)        顾客唤醒收银员

    sem_t finished[NUM_CUSTOM];    // (0)        通知顾客结账完毕

}line;

                                           

int main(int argc, char* argv[])

{

    int i, TotalNeeds = 0;

    srand(time(0));

    sem_init(&capacity, 0, NUM_CLERK);            // 店员人数

    line.number = 0;

    for(i = 0 ; i < NUM_CUSTOM ; i++)

    {

        TotalNeeds += IceNum[i] = rand()%4 + 1;

        pthread_create(&cuThread[i], NULL, Customer, (void *)i);    //创建顾客线程并传入顾客顺序号

        sem_init(&line.finished[i], 0, 0);                            //

    }

    pthread_create(&caThread, NULL, Cashier, (void *)NULL);            //创建收银员线程,无参数

    int numChecked = 0;                    //记录老板核查的总数

    int numCheckedAndPassed = 0;        //记录核查通过的总数

    plan((int)TotalNeeds);

    inspect.passed = false;

    sem_init(&inspect.requested, 0, 0);

    sem_init(&inspect.finished, 0, 0);

    sem_init(&inspect.locked, 0, 1);

    while(numCheckedAndPassed < (int)TotalNeeds)    //当合格数未到总需求,继续核查

    {

        sem_wait(&inspect.requested);                //等待核查请求

        numChecked++;                                //核查数加1

        inspect.passed = rand()%2 ? true : false;    //模拟核查结果

        if(inspect.passed)                            //如果合格,记录

             numCheckedAndPassed++;

        progress(inspect.passed, numChecked, numCheckedAndPassed, (int)TotalNeeds);

        sem_post(&inspect.finished);                //完成核查

    }

    for(i=0; i<NUM_CUSTOM; i++)

        pthread_join(cuThread[i], NULL);

    pthread_join(maThread, NULL);

    pthread_join(caThread, NULL);

    return 0;

}

void *Customer(void *index) // void Customer(int numIceCream)

{

    pthread_t clThread[4];

    sem_t clerkDone[4];        //(0)                    //建立只有自己才能够识别的信号量

    int tid = (int)index;

    int numIceCream = IceNum[tid];

    printf("顾客%.2d:购买冰淇淋%d个。\n", tid, numIceCream);

    sem_init(&line.numLock, 0, 1);

    for(int i = 0 ; i < (int)numIceCream ; i++) {    //创建店员线程

        sem_wait(&capacity);

        sem_init(&clerkDone[i], 0, 0);

        pthread_create(&clThread[i], NULL, Clerk, (void *)clerkDone[i]);    

    }

    for(i = 0 ; i < (int)numIceCream ; i++)    //等待制作完成

        sem_wait(&clerkDone[i]);

    sem_wait(&line.numLock);                //进入临界区,获得排列号

    int place = line.number++;

    sem_post(&line.numLock);

    

    WalkToCashier(tid, numIceCream, place);    //准备结帐

    sem_post(&line.requested);                //发送请求(这里的requested可以累加)

    sem_wait(&line.finished[place]);        //等待处理完成

    printf("顾客%.2d:离店。\n", tid);

    pthread_exit(0);

    return NULL;

}

void *Clerk(void *clerkDone) // void Clerk(Semosphere clerkDone)

{

    bool passed = false;

    while(!passed)                        //如果没有通过,就一直做

    {

        MakeIceCream();                    //制作过程

        sem_wait(&inspect.locked);        //等待获得老板办公室权限

        sem_post(&i
4000
nspect.requested);    //给老板发送请求

        sem_wait(&inspect.finished);    //等待老板核查

        passed = inspect.passed;        //获取检验结果

        sem_post(&inspect.locked);        //出办公室要关门

    }

    sem_post((sem_t *)&clerkDone);        //将冰淇淋交给顾客

    sem_post(&capacity);                //招呼下一个顾客

    return NULL;

}

void *Cashier(void *arg) // void cashier()

{

    sem_init(&line.requested, 0, 0);    //

    for(int i=0; i<NUM_CUSTOM; i++)        //依次处理

    {

        sem_wait(&line.requested);        //等待请求

        CashOut(i);                        //收钱

        sem_post(&line.finished[i]);    //通知对应顾客

    }

    return NULL;

}

void plan(int TotalNeeds)

{

    printf("老板:计划制作%d个冰淇淋。\n", TotalNeeds);

}

void progress(bool passed, int numChecked, int numCheckedAndPassed, int TotalNeeds)

{

    int sval;

    char msg[20];

    sem_getvalue (&capacity, &sval);

    if( sval >= 0 )

        sprintf(msg, "%d位员工在工作。", NUM_CLERK - sval);

    else

        sprintf(msg, "%d位顾客在等待。", -sval);

    if(passed)

        printf("老板:检查合格。合格率:%2.1f%%, 进度%d/%d, %s\n",

            100.0*numCheckedAndPassed/numChecked, numCheckedAndPassed, TotalNeeds, msg);

    else

        printf("老板:检查不合格。合格率:%2.1f%%, 进度%d/%d, %s\n",

            100.0*numCheckedAndPassed/numChecked, numCheckedAndPassed, TotalNeeds, msg);

}

void MakeIceCream()

{

    puts("店员:制作冰淇淋...");

    Sleep(400);

}

void WalkToCashier(int tid, int numIceCream, int n)

{

    printf("顾客%.2d:获得%d个冰淇淋,去收银台取号%d...\n", tid, numIceCream, n);

    Sleep(100);

}

void CashOut(int i)

{

    printf("收银员:顾客%d货款付讫。\n", i);

    Sleep(100);

}

【输出结果】

顾客00:购买冰淇淋2个。

顾客02:购买冰淇淋4个。

顾客04:购买冰淇淋3个。

顾客03:购买冰淇淋3个。

顾客01:购买冰淇淋4个。

顾客07:购买冰淇淋3个。

顾客06:购买冰淇淋3个。

顾客05:购买冰淇淋4个。

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:计划制作34个冰淇淋。

店员:制作冰淇淋...

顾客08:购买冰淇淋4个。

店员:制作冰淇淋...

顾客09:购买冰淇淋4个。

老板:检查不合格。合格率:0.0%, 进度0/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:0.0%, 进度0/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:33.3%, 进度1/34, 9位顾客在等待。

老板:检查不合格。合格率:25.0%, 进度1/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:40.0%, 进度2/34, 8位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查合格。合格率:50.0%, 进度3/34, 9位顾客在等待。

老板:检查不合格。合格率:42.9%, 进度3/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:37.5%, 进度3/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:33.3%, 进度3/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:40.0%, 进度4/34, 8位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查不合格。合格率:36.4%, 进度4/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:33.3%, 进度4/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:38.5%, 进度5/34, 9位顾客在等待。

老板:检查不合格。合格率:35.7%, 进度5/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:33.3%, 进度5/34, 8位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查不合格。合格率:31.3%, 进度5/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:35.3%, 进度6/34, 9位顾客在等待。

老板:检查合格。合格率:38.9%, 进度7/34, 9位顾客在等待。

顾客00:获得2个冰淇淋,去收银台取号0...

店员:制作冰淇淋...

老板:检查合格。合格率:42.1%, 进度8/34, 9位顾客在等待。

老板:检查合格。合格率:45.0%, 进度9/34, 9位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

收银员:顾客0货款付讫。

顾客00:离店。

老板:检查不合格。合格率:42.9%, 进度9/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:40.9%, 进度9/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:43.5%, 进度10/34, 9位顾客在等待。

老板:检查不合格。合格率:41.7%, 进度10/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:44.0%, 进度11/34, 8位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查不合格。合格率:42.3%, 进度11/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:44.4%, 进度12/34, 9位顾客在等待。

老板:检查不合格。合格率:42.9%, 进度12/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:41.4%, 进度12/34, 8位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:40.0%, 进度12/34, 8位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查合格。合格率:41.9%, 进度13/34, 9位顾客在等待。

老板:检查合格。合格率:43.8%, 进度14/34, 8位顾客在等待。

老板:检查合格。合格率:45.5%, 进度15/34, 9位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:47.1%, 进度16/34, 8位顾客在等待。

老板:检查不合格。合格率:45.7%, 进度16/34, 7位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查合格。合格率:47.2%, 进度17/34, 7位顾客在等待。

老板:检查不合格。合格率:45.9%, 进度17/34, 6位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:44.7%, 进度17/34, 6位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:46.2%, 进度18/34, 6位顾客在等待。

顾客04:获得3个冰淇淋,去收银台取号1...

老板:检查不合格。合格率:45.0%, 进度18/34, 6位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

收银员:顾客1货款付讫。

顾客04:离店。

老板:检查合格。合格率:46.3%, 进度19/34, 7位顾客在等待。

老板:检查不合格。合格率:45.2%, 进度19/34, 6位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:46.5%, 进度20/34, 6位顾客在等待。

老板:检查不合格。合格率:45.5%, 进度20/34, 5位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:46.7%, 进度21/34, 6位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查合格。合格率:47.8%, 进度22/34, 5位顾客在等待。

老板:检查合格。合格率:48.9%, 进度23/34, 4位顾客在等待。

顾客02:获得4个冰淇淋,去收银台取号2...

店员:制作冰淇淋...

店员:制作冰淇淋...

老板:检查不合格。合格率:47.9%, 进度23/34, 4位顾客在等待。

店员:制作冰淇淋...

老板:检查不合格。合格率:46.9%, 进度23/34, 4位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:48.0%, 进度24/34, 4位顾客在等待。

顾客07:获得3个冰淇淋,去收银台取号3...

店员:制作冰淇淋...

收银员:顾客2货款付讫。

顾客02:离店。

收银员:顾客3货款付讫。

顾客07:离店。

老板:检查不合格。合格率:47.1%, 进度24/34, 4位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:48.1%, 进度25/34, 4位顾客在等待。

顾客06:获得3个冰淇淋,去收银台取号4...

店员:制作冰淇淋...

老板:检查合格。合格率:49.1%, 进度26/34, 4位顾客在等待。

顾客03:获得3个冰淇淋,去收银台取号5...

老板:检查不合格。合格率:48.1%, 进度26/34, 3位顾客在等待。

店员:制作冰淇淋...

老板:检查合格。合格率:49.1%, 进度27/34, 3位顾客在等待。

店员:制作冰淇淋...

店员:制作冰淇淋...

收银员:顾客4货款付讫。

收银员:顾客5货款付讫。

顾客06:离店。

顾客03:离店。

老板:检查合格。合格率:50.0%, 进度28/34, 2位顾客在等待。

老板:检查合格。合格率:50.9%, 进度29/34, 1位顾客在等待。

老板:检查合格。合格率:51.7%, 进度30/34, 1位顾客在等待。

老板:检查合格。合格率:52.5%, 进度31/34, 5位员工在工作。

顾客05:获得4个冰淇淋,去收银台取号6...

老板:检查合格。合格率:53.3%, 进度32/34, 4位员工在工作。

顾客01:获得4个冰淇淋,去收银台取号7...

店员:制作冰淇淋...

店员:制作冰淇淋...

收银员:顾客6货款付讫。

顾客05:离店。

收银员:顾客7货款付讫。

顾客01:离店。

老板:检查不合格。合格率:52.5%, 进度32/34, 2位员工在工作。

店员:制作冰淇淋...

老板:检查合格。合格率:53.2%, 进度33/34, 2位员工在工作。

顾客08:获得4个冰淇淋,去收银台取号8...

收银员:顾客8货款付讫。

顾客08:离店。

老板:检查合格。合格率:54.0%, 进度34/34, 1位员工在工作。

顾客09:获得4个冰淇淋,去收银台取号9...

收银员:顾客9货款付讫。

顾客09:离店。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息