23、多进程编程练习题

1. 进程同步问题:实现一个多进程银行转账系统,使用锁保证余额操作的原子性

import multiprocessing


# 定义一个银行账户类
class BankAccount:
    def __init__(self, balance, use_shared_mode=False):
        self.use_shared_mode = use_shared_mode
        if use_shared_mode:
            # 使用 Manager 来创建共享的余额对象
            manager = multiprocessing.Manager()
            self.balance = manager.Value('i', balance)
        else:
            # 账户初始余额
            self.balance = balance
        # 创建一个锁对象,用于保证余额操作的原子性
        self.lock = multiprocessing.Lock()

    def transfer(self, amount):
        # 获取锁,确保同一时间只有一个进程可以修改余额
        self.lock.acquire()
        try:
            if self.use_shared_mode:
                current_balance = self.balance.value
            else:
                current_balance = self.balance
            # 检查余额是否足够
            if current_balance >= amount:
                if self.use_shared_mode:
                    self.balance.value -= amount
                    print(f"成功转出 {amount} 元,当前余额: {self.balance.value} 元")
                else:
                    self.balance -= amount
                    print(f"成功转出 {amount} 元,当前余额: {self.balance} 元")
            else:
                print("余额不足,转账失败")
        finally:
            # 释放锁,允许其他进程继续操作
            self.lock.release()


# 定义转账函数,用于在进程中执行转账操作
def transfer_money(account, amount):
    account.transfer(amount)


if __name__ == "__main__":
    # 切换是否使用共享模式,True 为使用,False 为不使用
    use_shared_mode = False

    # 创建一个初始余额为 1000 元的银行账户
    account = BankAccount(1000, use_shared_mode)

    # 定义多个转账金额
    transfer_amounts = [200, 300, 500, 100]

    # 创建进程列表
    processes = []
    for amount in transfer_amounts:
        # 创建一个进程,目标函数为 transfer_money,传入账户对象和转账金额
        p = multiprocessing.Process(target=transfer_money, args=(account, amount))
        processes.append(p)
        # 启动进程
        p.start()

    # 等待所有进程执行完毕
    for p in processes:
        p.join()

    if use_shared_mode:
        final_balance = account.balance.value
    else:
        final_balance = account.balance
    # 打印最终账户余额
    print(f"最终账户余额: {final_balance} 元")

2. 性能优化:对比进程池大小设置为CPU核数2倍与默认值的执行效率差异

# 定义一个 CPU 密集型任务
def cpu_intensive_task(n):
    result = 0
    for i in range(n):
        result += i
    return result


if __name__ == "__main__":
    # 获取 CPU 核心数
    cpu_count = multiprocessing.cpu_count()

    # 定义任务数量
    task_count = 20
    # 定义每个任务的计算量
    task_size = 10 ** 7
    print(task_size)
    # 情况 1:使用默认大小的进程池(通常是 CPU 核心数)
    start_time_default = time.time()
    with multiprocessing.Pool() as pool:
        results_default = pool.map(cpu_intensive_task, [task_size] * task_count)
    end_time_default = time.time()
    time_taken_default = end_time_default - start_time_default
    print(f"默认进程池大小({cpu_count})执行时间: {time_taken_default:.4f} 秒")

    # 情况 2:使用 CPU 核数 2 倍大小的进程池
    pool_size_double = cpu_count * 2
    start_time_double = time.time()
    with multiprocessing.Pool(processes=pool_size_double) as pool:
        results_double = pool.map(cpu_intensive_task, [task_size] * task_count)
    end_time_double = time.time()
    time_taken_double = end_time_double - start_time_double
    print(f"进程池大小为 CPU 核数 2 倍({pool_size_double})执行时间: {time_taken_double:.4f} 秒")

    # 输出对比结果
    if time_taken_default < time_taken_double:
        print("默认进程池大小执行效率更高。")
    elif time_taken_default > time_taken_double:
        print("进程池大小为 CPU 核数 2 倍时执行效率更高。")
    else:
        print("两种进程池大小执行效率相同。")

3. 僵尸进程处理:编写一个能自动回收子进程的进程监视器

## **僵尸进程处理**:编写一个能自动回收子进程的进程监视器

import os
import time
import multiprocessing


# 定义子进程要执行的任务
def child_task():
    print(f"子进程 {os.getpid()} 开始运行")
    time.sleep(2)
    print(f"子进程 {os.getpid()} 结束运行")


if __name__ == "__main__":
    # 创建多个子进程
    processes = []
    for _ in range(3):
        p = multiprocessing.Process(target=child_task)
        p.start()
        processes.append(p)

    # 主进程等待所有子进程结束
    for p in processes:
        p.join()

    print("所有子进程已结束,主进程退出。")
#
# import os
# import signal
# import time
# import multiprocessing
#
#
# def child_task():
#     """子进程执行的任务"""
#     print(f"子进程 {os.getpid()} 开始运行")
#     time.sleep(2)
#     print(f"子进程 {os.getpid()} 结束运行")
#
#
# def signal_handler(signum, frame):
#     """信号处理函数,用于回收子进程"""
#     while True:
#         try:
#             # 非阻塞方式等待子进程结束
#             pid, status = os.waitpid(-1, os.WNOHANG)
#             if pid == 0:
#                 break
#             print(f"已回收子进程 {pid},状态码: {status}")
#         except OSError:
#             break
#
#
# if __name__ == "__main__":
#     # 注册 SIGCHLD 信号处理函数 有平台限制
#     signal.signal(signal.SIGCHLD, signal_handler)
#
#     # 创建并启动子进程
#     processes = []
#     for _ in range(3):
#         p = multiprocessing.Process(target=child_task)
#         p.start()
#         processes.append(p)
#
#     print("主进程继续执行其他任务...")
#     try:
#         while True:
#             time.sleep(1)
#     except KeyboardInterrupt:
#         print("主进程收到终止信号,退出...")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wolf犭良

谢谢您的阅读与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值