用进程同步问题解决售票员与乘客问题

用进程同步方法解决售票员与乘客问题
【问题描述】了解进程同步的概念,理解信号量机制的原理,掌握运用信号量解决进程同步问题的方法,进而学会运用进程的同步与互斥。
【设计要求】编程序模拟车站售票厅内进程同步问题,售票厅任何时刻最多可容纳20名购票者进入,否则需要在外面等待。每个购票者可看成一个进程。

这是一个典型的生产者-消费者问题,可以使用信号量来解决。

首先,我们可以定义一个信号量 ticket_lock 来保证对票数的操作是原子的。

然后,我们可以定义一个信号量 ticket_count 来表示当前还有多少张票可供售。

接着,我们可以定义一个信号量 ticket_room 来表示售票厅还有多少空位可供乘客进入。

最后,我们可以定义两个进程分别表示售票员和乘客。

售票员进程会不断地循环,每次检查是否有乘客在等待。如果有,就会尝试获取 ticket_count 和 ticket_room 两个信号量的锁。如果成功,就可以将 ticket_count 减 1,表示卖出了一张票,并将 ticket_room 减 1,表示乘客进入售票厅。

乘客进程也会不断地循环,每次检查是否有空位可以进入售票厅。如果有,就会尝试获取 ticket_room 信号量的锁。如果成功,就可以将 ticket_room 减 1,表示乘客进入售票厅。

这里是一个示例代码,它使用了 C++11 的 和 头文件来实现信号量机制:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

const int MAX_TICKET_COUNT = 20;  // 最多允许 20 位乘客进入售票厅

int ticket_count = MAX_TICKET_COUNT;  // 当前剩余的票数
int ticket_room = MAX_TICKET_COUNT;   // 当前剩余的空位数

std::mutex ticket_lock;  // 互斥锁,用于保护 ticket_count 和 ticket_room
std::condition_variable ticket_cv;  // 条件变量,用于通知售票员有乘客在等待

void seller() {
  while (true) {
    std::unique_lock<std::mutex> lock(ticket_lock);  // 获取 ticket_count 和 ticket_room 的锁
    // 等待 ticket_count > 0 并且 ticket_room > 0
    ticket_cv.wait(lock, []{return ticket_count > 0 && ticket_room > 0;});

    // 售出一张票
    ticket_count--;
    // 乘客进入售票厅
    ticket_room--;
    std::cout << "Seller: sold a ticket, " << ticket_count << " tickets left." << std::endl;
  }
}

void passenger() {
  while (true) {
    std::unique_lock<std::mutex> lock(ticket_lock);  // 获取 ticket_room 的锁
    // 等待 ticket_room > 0
    ticket_cv.wait(lock, []{return ticket_room > 0;});

    // 乘客进入售票厅
    ticket_room--;
    std::cout << "Passenger: entered the ticket room." << std::endl;

    // 通知售票员有乘客在等待
    ticket_cv.notify_one();
  }
}

int main() {
  std::thread seller_thread(seller);
  std::thread passenger_thread(passenger);

  seller_thread.join();
  passenger_thread.join();

  return 0;
}

package cn.sunzn.synchronize;

public class SynchronizeCode {
   public static void main(String[] args) {
       new TicketSeller().start();
       new TicketSeller().start();
       new TicketSeller().start();
       new TicketSeller().start();
   }
}

class TicketSeller extends Thread {

   private static int ticket = 100;
   private static Object lock = new Object();

   public void run() {
       while (true) {
           synchronized (lock) {
               /************ 每次售票前进行判断 ************/
               if (ticket == 0) {
                   break;
               }

               /************ 模拟售票的网络延迟 ************/
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }

               /************ 符合条件后进行售票 ************/
               System.out.println(Thread.currentThread().getName() + " 售出了第 " + ticket-- + " 张票");
           }
       }
   }
}


基本是你的解决方案了

https://www.taodocs.com/p-1969936.html

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;//定义链表
 

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);//进程结束
    }
}

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);
    }
}

不知这篇实例【操作系统售票员与乘客】是否满足你的要求,链接:https://www.codenong.com/cs106712436/
【推荐理由,类型相似,讲解详细,注解清晰】