操作系统pv操作,信号初始量餐厅叫号排队安排座位
时间: 2025-07-07 22:02:37 浏览: 7
### ### 餐厅叫号系统中的 PV 操作与并发控制
在操作系统中,PV 操作是实现进程同步与互斥的重要机制。通过信号量(Semaphore)来管理共享资源的访问,可以有效避免多个进程同时访问同一资源而导致的竞争条件问题。
#### 信号量初始化设置原则
在餐厅叫号系统中,顾客到达后需要取号排队,服务员负责叫号并安排座位。当餐桌满座时,顾客需等待;当用餐完毕后,服务员清理餐桌,并释放资源供下一位顾客使用。这一过程涉及到多个共享资源的访问控制:
- **顾客队列**:用于存储待服务的顾客信息。
- **餐桌资源**:每张餐桌是一个可被占用或释放的资源。
- **服务员调度**:多个服务员可能同时尝试叫号,需确保一致性。
为了实现这些操作的原子性与互斥性,需要设置适当的信号量[^1]:
```python
# 初始化信号量
customer_queue = queue.Queue() # 顾客队列
available_tables = [True] * N # 假设有 N 张餐桌,True 表示可用
table_mutex = Semaphore(1) # 控制餐桌分配的互斥访问
call_number_mutex = Semaphore(1) # 叫号互斥锁
```
#### 顾客到达与取号逻辑
顾客到达后,应获取一个号码,并加入队列中等待叫号。为防止多个顾客同时修改队列,应使用 `P` 操作对队列进行加锁[^2]:
```python
def customer_arrives():
call_number_mutex.acquire() # P 操作,进入临界区
number = generate_next_number()
customer_queue.put(number)
call_number_mutex.release() # V 操作,退出临界区
```
#### 服务员叫号与安排座位逻辑
服务员从队列中取出下一个号码,并尝试为其分配一张合适的餐桌。若无空闲餐桌,则顾客需等待,直到有餐桌释放:
```python
def server_call_next():
if not customer_queue.empty():
number = customer_queue.get()
table_mutex.acquire() # 进入餐桌分配临界区
assigned_table = find_available_table()
if assigned_table is not None:
occupy_table(assigned_table)
print(f"请{number}号顾客就坐于餐桌{assigned_table}")
else:
customer_queue.put(number) # 若无空桌,将号码放回队列等待
table_mutex.release() # 释放餐桌资源
```
#### 顾客用餐完毕与餐桌释放逻辑
顾客用餐结束后通知服务员,服务员执行清理餐桌的操作,并释放对应的餐桌资源[^2]:
```python
def finish_dining(table_id):
table_mutex.acquire()
available_tables[table_id] = True # 标记餐桌为空闲
table_mutex.release()
```
#### 多服务员调度与负载均衡
当存在多个服务员时,可以通过轮询、优先级或响应比等方式选择最合适的服务员进行叫号。例如采用最短任务优先策略[^2]:
```python
servers = [Server(i, speed=1.0) for i in range(M)] # M个服务员
def select_server():
return min(servers, key=lambda s: s.current_load)
def assign_task_to_server(task_complexity):
selected = select_server()
selected.assign_task(task_complexity)
```
#### 完整流程模拟
结合以上逻辑,可以构建一个完整的餐厅叫号与座位安排模拟系统:
```python
import threading
from queue import Queue
from threading import Semaphore
N = 5 # 餐桌数量
M = 3 # 服务员数量
customer_queue = Queue()
available_tables = [True] * N
table_mutex = Semaphore(1)
call_number_mutex = Semaphore(1)
class Server:
def __init__(self, id, speed=1.0):
self.id = id
self.current_load = 0
self.speed = speed
def assign_task(self, task_complexity):
self.current_load += task_complexity / self.speed
def finish_task(self):
self.current_load = max(0, self.current_load - 1)
servers = [Server(i) for i in range(M)]
def customer_arrives():
call_number_mutex.acquire()
number = customer_queue.qsize() + 1
customer_queue.put(number)
print(f"顾客{number}已取号")
call_number_mutex.release()
def server_call_next():
if not customer_queue.empty():
number = customer_queue.get()
table_mutex.acquire()
assigned_table = next((i for i, val in enumerate(available_tables) if val), None)
if assigned_table is not None:
available_tables[assigned_table] = False
print(f"请{number}号顾客就坐于餐桌{assigned_table}")
threading.Timer(5, finish_dining, args=(assigned_table,)).start()
else:
customer_queue.put(number)
table_mutex.release()
def finish_dining(table_id):
table_mutex.acquire()
available_tables[table_id] = True
print(f"餐桌{table_id}已清理")
table_mutex.release()
# 启动服务员线程
for _ in range(M):
threading.Thread(target=lambda: [server_call_next() for _ in range(10)], daemon=True).start()
# 模拟顾客到达
for _ in range(20):
threading.Thread(target=customer_arrives).start()
```
---
阅读全文
相关推荐




















