进程锁(互斥锁)
进程锁(互斥锁)
(1)简介
-
进程锁(也称为互斥锁)是一种用于控制多个进程对共享资源访问的机制。在并发编程中,多个进程可能同时访问共享的数据,如果没有适当的同步机制,可能会导致数据不一致或其他问题。进程锁就是用来解决这个问题的一种同步工具。
-
互斥锁的基本思想是,在访问共享资源之前,进程首先必须获得锁。如果锁已经被其他进程获得,那么进程就必须等待,直到锁被释放。这样可以确保同一时刻只有一个进程可以访问共享资源,从而避免了竞态条件和数据不一致的问题。
(2)多个进程共享同一文件
- 文件当数据库,模拟抢票
- 并发运行,数据写入错乱
(1)未加锁示例
import random from multiprocessing import Process, Lock import time import json import os # 确定存储车票信息的文件路径 db_path = os.path.join(os.path.dirname(__file__), 'ticket_data.json') # 初始化车票数据 def init_data(): with open(file=db_path, mode='w', encoding='utf-8') as fp: json.dump({'ticket_number': 2}, fp) # 获取车票数据 def get_ticket(): with open(db_path, 'r', encoding='utf8') as f: ticket_dict = json.load(f) return ticket_dict # 保存车票数据 def save_ticket(ticket_dict): with open(db_path, 'w', encoding='utf8') as f: json.dump(ticket_dict, f) # 查询车票 def search_ticket(name): ticket_dict = get_ticket() print(f'用户:>>>{name} 正在查询余票:>>>{ticket_dict.get("ticket_number")}') # 购买车票 def buy_ticket(name): ticket_dict = get_ticket() # 模拟购票过程中的随机延迟 time.sleep(random.randint(1, 3)) if ticket_dict.get('ticket_number') > 0: ticket_dict['ticket_number'] -= 1 save_ticket(ticket_dict) print(f'用户:>>>{name} 买票成功!!') else: print(f'当前无余票!!') # 主函数,包括查询和购买操作 def main(name): search_ticket(name) buy_ticket(name) if __name__ == '__main__': # 初始化车票数据 init_data() # 创建进程列表 p_list = [] # 创建多个进程模拟多用户同时操作 for i in range(1, 5): p = Process(target=main, args=(i,)) p.start() p_list.append(p) # 等待所有进程执行完毕 for p in p_list: p.join() # 用户:>>>1 正在查询余票:>>>2 # 用户:>>>4 正在查询余票:>>>2 # 用户:>>>2 正在查询余票:>>>2 # 用户:>>>3 正在查询余票:>>>2 # 用户:>>>1 买票成功!! # 用户:>>>4 买票成功!! # 用户:>>>3 买票成功!! # 用户:>>>2 买票成功!!
(2)加锁
- 针对上述数据错乱问题,解决方式就是加锁处理
- 将并发变成串行牺牲效率,但是保证了数据的安全
import random from multiprocessing import Process, Lock import time import json import os # 确定存储车票信息的文件路径 db_path = os.path.join(os.path.dirname(__file__), 'ticket_data.json') # 初始化车票数据 def init_data(): with open(file=db_path, mode='w', encoding='utf-8') as fp: json.dump({'ticket_number': 2}, fp) # 获取车票数据 def get_ticket(): with open(db_path, 'r', encoding='utf8') as f: ticket_dict = json.load(f) return ticket_dict # 保存车票数据 def save_ticket(ticket_dict): with open(db_path, 'w', encoding='utf8') as f: json.dump(ticket_dict, f) # 查询车票 def search_ticket(name): ticket_dict = get_ticket() print(f'用户:>>>{name} 正在查询余票:>>>{ticket_dict.get("ticket_number")}') # 购买车票 def buy_ticket(name, mutex): ticket_dict = get_ticket() time.sleep(random.randint(1, 3)) if ticket_dict.get('ticket_number') > 0: ticket_dict['ticket_number'] -= 1 save_ticket(ticket_dict) print(f'用户:>>>{name} 买票成功!!') else: print(f'当前无余票!!') # 主函数,包括查询和购买操作 def main(name, mutex): search_ticket(name) # 请求互斥锁 mutex.acquire() try: buy_ticket(name, mutex) finally: # 释放互斥锁 mutex.release() if __name__ == '__main__': # 初始化车票数据 init_data() # 创建互斥锁 mutex = Lock() # 创建进程列表 p_list = [] # 创建多个进程模拟多用户同时购票操作 for i in range(1, 5): p = Process(target=main, args=(i, mutex)) p.start() p_list.append(p) # 等待所有进程执行完毕 for p in p_list: p.join() # 所有人都能查票成功,但是只有前两名购票成功 # 前两名是随机抢到的,不一定是按顺序(考虑到各种因素,如网络等) # 用户:>>>1 正在查询余票:>>>2 # 用户:>>>4 正在查询余票:>>>2 # 用户:>>>3 正在查询余票:>>>2 # 用户:>>>2 正在查询余票:>>>2 # 用户:>>>1 买票成功!! # 用户:>>>4 买票成功!! # 当前无余票!! # 当前无余票!!
mutex = Lock()
: 创建了一个互斥锁对象。mutex.acquire()
: 请求互斥锁,如果锁已经被其他进程占用,会阻塞等待。try
中的代码块:在互斥锁保护下执行购票操作。finally
中的代码块:无论购票操作是否成功,都会释放互斥锁,确保其他进程可以访问共享资源。- 进程列表
p_list
:存储了所有创建的进程对象,用于后续等待所有进程执行完毕。
本文作者:ssrheart
本文链接:https://www.cnblogs.com/ssrheart/p/17970415
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步