MST

星途 面试题库

面试题:Python银行出纳员服务器角色的并发处理

在银行出纳员服务器角色场景中,可能会同时收到多个客户的交易请求。请用Python的多线程或异步编程(asyncio)实现一个简单的服务器端程序,能够并发处理客户的取款和存款请求,并且要保证数据的一致性,避免出现竞态条件。请给出完整的代码实现及必要的注释。
16.9万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
import asyncio
import threading

# 银行账户类
class BankAccount:
    def __init__(self, initial_balance=0):
        self.balance = initial_balance
        self.lock = threading.Lock()  # 使用锁来避免竞态条件

    # 存款方法
    async def deposit(self, amount):
        with self.lock:
            self.balance += amount
            print(f"存款 {amount} 成功,当前余额: {self.balance}")

    # 取款方法
    async def withdraw(self, amount):
        with self.lock:
            if self.balance >= amount:
                self.balance -= amount
                print(f"取款 {amount} 成功,当前余额: {self.balance}")
            else:
                print("余额不足,取款失败")


# 模拟处理客户请求
async def handle_customer(account, request_type, amount):
    if request_type == "deposit":
        await account.deposit(amount)
    elif request_type == "withdraw":
        await account.withdraw(amount)


# 主函数
async def main():
    account = BankAccount()
    requests = [
        ("deposit", 100),
        ("withdraw", 50),
        ("deposit", 200),
        ("withdraw", 300)
    ]
    tasks = []
    for request_type, amount in requests:
        task = asyncio.create_task(handle_customer(account, request_type, amount))
        tasks.append(task)
    await asyncio.gather(*tasks)


if __name__ == "__main__":
    asyncio.run(main())
  1. BankAccount:
    • __init__方法初始化账户余额,并创建一个线程锁lock用于同步访问账户余额。
    • deposit方法实现存款逻辑,使用with self.lock语句来获取锁,确保在存款操作期间其他线程无法修改余额,操作完成后自动释放锁。
    • withdraw方法实现取款逻辑,同样使用锁来保证数据一致性,并且在取款前检查余额是否足够。
  2. handle_customer函数:
    • 根据请求类型(存款或取款)调用账户对应的方法来处理客户请求。
  3. main函数:
    • 创建一个BankAccount实例。
    • 定义一系列客户请求。
    • 使用asyncio.create_task创建任务来并发处理每个客户请求,并将任务添加到tasks列表中。
    • 最后使用asyncio.gather等待所有任务完成。
  4. if __name__ == "__main__":
    • 使用asyncio.run来运行main异步函数。