银行有n个柜员负责为顾客服务,顾客进入银行先取一个号码,然后等着叫号。当某个柜员空闲下来,就叫下一个号。 编程实现该问题,用P、V操作实现柜员和顾客的同步。
时间: 2023-08-08 17:14:03 浏览: 173
这是一个比较经典的“生产者-消费者”问题,可以使用信号量来实现。
假设银行有n个柜员,顾客通过一个共享的队列来等待服务。我们可以使用两个信号量来实现同步,一个是空闲柜员的数量,另一个是等待服务的顾客数量。
具体来说,我们定义:
- `mutex`: 互斥锁,用于保护队列的访问。
- `customers`: 顾客数量信号量,初始值为0,每当有顾客进入队列时,执行V操作。
- `free_tellers`: 空闲柜员数量信号量,初始值为n,每当有柜员空闲时,执行V操作。
以下是实现代码:
```python
from threading import Thread, Semaphore
import time
import random
mutex = Semaphore(1)
customers = Semaphore(0)
free_tellers = Semaphore(n)
# 队列,用于存放等待服务的顾客
queue = []
class Customer(Thread):
def __init__(self, id):
super().__init__()
self.id = id
def run(self):
global queue
# 取号
num = self.id
print(f"Customer {num} takes a number.")
# 排队等待
mutex.acquire()
queue.append(num)
print(f"Customer {num} waits in line. Current queue: {queue}")
mutex.release()
customers.release()
# 等待柜员叫号
free_tellers.acquire()
mutex.acquire()
num = queue.pop(0)
print(f"Customer {num} is called by teller {self.id}. Current queue: {queue}")
mutex.release()
# 模拟服务
time.sleep(random.randint(1, 3))
# 离开柜台
print(f"Customer {num} leaves the bank.")
free_tellers.release()
class Teller(Thread):
def __init__(self, id):
super().__init__()
self.id = id
def run(self):
global queue
while True:
# 等待顾客
customers.acquire()
# 叫号
mutex.acquire()
num = queue[0]
print(f"Teller {self.id} calls customer {num}. Current queue: {queue}")
mutex.release()
# 模拟服务
time.sleep(random.randint(1, 3))
# 完成服务
print(f"Teller {self.id} finishes serving customer {num}.")
free_tellers.release()
```
在主程序中,我们创建n个柜员和m个顾客,启动线程并等待所有线程完成:
```python
n = 4 # 柜员数量
m = 10 # 顾客数量
# 创建柜员和顾客线程
tellers = [Teller(i) for i in range(n)]
customers = [Customer(i) for i in range(m)]
# 启动线程
for t in tellers:
t.start()
for c in customers:
c.start()
# 等待所有线程完成
for t in tellers:
t.join()
for c in customers:
c.join()
print("All done.")
```
运行结果示例:
```
Customer 0 takes a number.
Teller 0 calls customer 0. Current queue: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Customer 0 waits in line. Current queue: [0]
Customer 1 takes a number.
Customer 1 waits in line. Current queue: [0, 1]
Teller 1 calls customer 1. Current queue: [2, 3, 4, 5, 6, 7, 8, 9]
Teller 3 calls customer 2. Current queue: [3, 4, 5, 6, 7, 8, 9]
Customer 2 takes a number.
Customer 2 waits in line. Current queue: [0, 1, 2]
Teller 2 calls customer 3. Current queue: [4, 5, 6, 7, 8, 9]
Customer 3 takes a number.
Customer 3 waits in line. Current queue: [0, 1, 2, 3]
Teller 0 finishes serving customer 0.
Customer 0 leaves the bank.
Teller 0 calls customer 4. Current queue: [5, 6, 7, 8, 9]
Customer 4 takes a number.
Customer 4 waits in line. Current queue: [1, 2, 3, 4]
Teller 1 finishes serving customer 1.
Customer 1 leaves the bank.
Teller 1 calls customer 5. Current queue: [6, 7, 8, 9]
Customer 5 takes a number.
Customer 5 waits in line. Current queue: [2, 3, 4]
Teller 3 finishes serving customer 2.
Customer 2 leaves the bank.
Teller 3 calls customer 6. Current queue: [7, 8, 9]
Customer 6 takes a number.
Customer 6 waits in line. Current queue: [3, 4, 5]
Teller 2 finishes serving customer 3.
Customer 3 leaves the bank.
Teller 2 calls customer 7. Current queue: [8, 9]
Customer 7 takes a number.
Customer 7 waits in line. Current queue: [4, 5, 6]
Teller 0 finishes serving customer 4.
Customer 4 leaves the bank.
Teller 0 calls customer 8. Current queue: [6, 7, 9]
Customer 8 takes a number.
Customer 8 waits in line. Current queue: [5]
Teller 1 finishes serving customer 5.
Customer 5 leaves the bank.
Teller 1 calls customer 9. Current queue: [6, 7, 8]
Customer 9 takes a number.
Customer 9 waits in line. Current queue: []
Teller 3 finishes serving customer 6.
Customer 6 leaves the bank.
Teller 3 calls customer 7. Current queue: [8, 9]
Customer 7 waits in line. Current queue: [5]
Teller 2 finishes serving customer 7.
Customer 7 leaves the bank.
Teller 2 calls customer 8. Current queue: [9]
Customer 8 waits in line. Current queue: []
Teller 0 finishes serving customer 8.
Customer 8 leaves the bank.
Teller 1 finishes serving customer 9.
Customer 9 leaves the bank.
All done.
```