用进程同步方法解决售票员与乘客问题
【问题描述】了解进程同步的概念,理解信号量机制的原理,掌握运用信号量解决进程同步问题的方法,进而学会运用进程的同步与互斥。
【设计要求】编程序模拟车站售票厅内进程同步问题,售票厅任何时刻最多可容纳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/
【推荐理由,类型相似,讲解详细,注解清晰】