操作系统售票员与乘客


设计要求:编程序模拟车站售票厅进程同步问题,售票厅任何时刻最多可容纳20名购票者进入,否则需要在外面等待。每个购票者可以看成一个进程。

售票厅任何时刻最多可容纳20名购票者进入,当售票大厅超过20人时,系统提示乘客需退出大厅等待;当大厅中人数少于或等于20人时,售票员开始售票,并提示等待的乘客进入大厅;

由于售票大厅是缓存区,最大容量为20,因此会出现3中情况:

① 若此时售票厅里人数为零时,则程序会提醒售票大厅为空,售票员的进程阻塞,直到购票者的进程运行完才唤醒该进程;

② 当进入售票厅内的人数还没有20时,进程将继续执行,则表示售票者的进程和购票者的进程都能执行;

③ 由于程序中的售票厅最大只能容纳20个人,所以,当售票厅内的人数进入将20时,则程序会提醒用户售票大厅的人数已满,请排队等候,购票者进程阻塞,直到售票者的进程运行完才唤醒该进程。

由于是多个购票者和多个售票者对应多个缓存区,因此,设置3个信号量:

同步信号量empty表示空缓存单元的个数,初值为20;

同步信号量full表示满缓冲单元的个数,初值为0;

互斥信号量mutex表示互斥使用的整个缓存池,初值为1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1、建立信号量
typedef int semaphore;
typedef int item;
item buffer[N] = {0};//缓存区
int in = 0;//进来缓存区的位置
int out = 0;//出去的缓存区的位置
int num=0;//此时缓存区的人数
int proCount = 0;//
int purchaserNum,sellerNum;//售票者的人数,乘客的人数
semaphore mutex = 1, empty = N, full = 0, proCmutex = 1;
//信号量的定义,empty=空的缓存区数量,full=满的缓存区的数量,
proCmutex=1//生产乘客的信号量
typedef struct Node{
    pthread_t temp;  //进程
    struct Node *next; //指针域
}Node,*LinkList;//定义链表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2、乘客进程
void * purchaser(void * a){
    while(true){
        while(proCmutex <= 0);//判断乘客是否产生
        proCmutex--;//已产生
        proCount++;//乘客的数量


        while(empty <= 0){
            printf("售票大厅已满!请排队等候\n");
        }//P(empty),判断缓存区是否为满

        while(mutex <= 0);//P(mutex),判断缓冲区是否被占用
        mutex--;//将缓存区的状态变为正在被调用

        if(buffer[in]==0)
            buffer[in] = proCount;//将进来的乘客序号放入缓冲区
        in = (in + 1) % N;//进来的指针推进一位
        full++;        //V(full),表示满的缓存区增加
        num++;         //缓冲区的人数加一
        printf("第%d乘客已进,此时售票大厅的人数为%d\n",proCount,num);


        empty--;     //空的缓存区减少,乘客进来了缓存区
        mutex++;     //V(mutex),释放缓冲区

        proCmutex++;//乘客已经进入售票大厅完,可再产生一名新的乘客

        Sleep(sleepTime);
        pthread_exit(0);//进程结束
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
3、售票员进程
void * seller(void *b){
    while(true){
        while(full <= 0){
            printf("售票大厅为空!\n");
            if(proCount==purchaserNum&&proCmutex==1)//判断售票员进程结束的标志:乘客全部离开售票大厅
                exit(0);//进程结束
        }//P(full),判断缓冲区是否为空


        while(mutex <= 0);//P(mutex),判断缓冲区是否被占用
        mutex--;//将缓存区的状态变为正在被调用
        empty++;//V(empty),表示空的缓存区增加


        int nextc = buffer[out];//找出离开位置的序号
        buffer[out] = 0;//售票完将离开售票大厅,此时该位置为0
        out = (out + 1) % N;//离开的指针加一
        if(nextc!=0)
        {
            num--;//此时售票大厅的人数减一
            full--;//表示满的缓冲区减少,乘客离开了缓存区
            printf("\t\t\t\t第%d乘客已走,此时售票大厅的人数为%d\n", nextc,num);
        }


        mutex++;//V(mutex),释放缓冲区
        Sleep(sleepTime);
    }
}