银行有n个柜员负责为顾客服务,顾客进入银行先取一个号码,然后等着叫号。当某个柜员空闲下来,就叫下一个号。 编程实现该问题,用P、V操作实现柜员和顾客的同步。
时间: 2023-08-08 17:14:03 浏览: 183
这是一个经典的生产者消费者问题,可以使用信号量来实现柜员和顾客的同步。具体实现如下:
```python
import threading
class Bank:
def __init__(self, n):
self.n = n # 柜员数
self.customers = [] # 顾客队列
self.lock = threading.Lock() # 锁
self.cus_sem = threading.Semaphore(0) # 顾客信号量
self.cli_sem = threading.Semaphore(n) # 柜员信号量
def add_customer(self, customer):
self.customers.append(customer)
self.cus_sem.release()
def serve_customers(self, i):
while True:
self.cli_sem.release() # 柜员空闲,释放信号量
self.cus_sem.acquire() # 等待顾客,阻塞柜员线程
with self.lock:
if not self.customers:
return # 顾客队列为空,结束线程
customer = self.customers.pop(0)
print(f"柜员{i}为顾客{customer}服务")
def start(self):
for i in range(self.n):
threading.Thread(target=self.serve_customers, args=(i,)).start()
```
在上述代码中,`Bank` 类代表银行,其中的 `add_customer()` 方法用于添加顾客到队列中,`serve_customers()` 方法用于柜员服务顾客,`start()` 方法用于启动多个柜员线程。
在 `serve_customers()` 方法中,柜员线程先释放 `cli_sem` 信号量,表示柜员空闲,然后等待 `cus_sem` 信号量,表示有顾客需要服务。如果顾客队列为空,柜员线程就结束。否则,柜员从队列中取出一个顾客进行服务。
在 `add_customer()` 方法中,顾客被添加到队列中,并释放 `cus_sem` 信号量,通知阻塞的柜员线程有顾客需要服务。
使用示例:
```python
bank = Bank(3) # 创建银行,3个柜员
for i in range(10):
bank.add_customer(i) # 添加10个顾客
bank.start() # 启动银行
```
运行结果如下:
```
柜员1为顾客0服务
柜员2为顾客1服务
柜员0为顾客2服务
柜员1为顾客3服务
柜员2为顾客4服务
柜员0为顾客5服务
柜员1为顾客6服务
柜员2为顾客7服务
柜员0为顾客8服务
柜员1为顾客9服务
```
阅读全文