1. 进程同步的必要性
在多进程编程中,当多个进程需要访问共享资源时,会出现竞争条件问题。例如火车票售卖系统中,如果多个售票窗口同时读取和修改剩余票数,可能导致数据不一致。
1.1 竞争条件示例
from multiprocessing import Process, Value
def sell_tickets(tickets):
for _ in range(1000):
tickets.value -= 1 # 非原子操作
if __name__ == '__main__':
tickets = Value('i', 10000)
processes = [Process(target=sell_tickets, args=(tickets,))
for _ in range(10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(f"剩余票数: {tickets.value}") # 结果不确定,可能大于0
在多进程环境下,多个进程可以同时执行。像代码里的tickets.value -= 1操作,实际上并非原子操作。它包含读取tickets.value的值、对该值减 1、再把新值写回tickets.value这几个步骤。当多个进程同时执行这一操作时,就可能出现数据不一致的状况。比如,两个进程同时读取到剩余票数为 100,各自减 1 后都写回 99,而实际上应该是 98。
2. 锁(Lock)机制
锁机制可以保证同一时间只有一个进程能够访问共享资源。当一个进程获取到锁之后,其他进程就必须等待该进程释放锁,才能继续访问共享资源。这样就能避免多个进程同时修改共享资源,从而解决竞争条件问题。
2.1 基础锁使用
from multiprocessing import Process, Lock, Value
def sell_tickets(tickets, lock):
for _ in range(1000):
lock.acquire()
tickets.value -= 1
lock.release()
if __name__ == '__main__':
tickets = Value('i', 10000)
lock = Lock()
processes = [Process(target=sell_tickets, args=(tickets, lock))
for _ in range(10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(f"剩余票数: {tickets.value}")
在上述代码中,lock.acquire()用于获取锁,一旦某个进程获取到锁,其他进程就只能等待。tickets.value -= 1是对共享资源的修改操作,由于有锁的保护,同一时间只有一个进程能执行这一操作。lock.release()用于释放锁,释放后其他进程就可以竞争获取锁。
2.2 上下文管理器简化
from multiprocessing import Process, Lock, Value
def sell_tickets(tickets, lock):
for _ in range(1000):
with lock: # 自动获取和释放锁
tickets.value -= 1
if __name__ == '__main__':
tickets = Value('i', 10000)
loc

最低0.47元/天 解锁文章
2399

被折叠的 条评论
为什么被折叠?



