本文共 2569 字,大约阅读时间需要 8 分钟。
当我们编写多进程程序时,资源管理可能会遇到竞态条件或死锁问题。一个常见的解决方案是使用Lock
。理解Lock
的使用是掌握多进程编程的关键。
应用场景举例:
假设我们有一个厕所资源,只能供一位人使用。如果有多个进程同时请求使用这个资源,怎么办?我们需要确保只有一个人能使用厕所,其他人的请求必须等待处理完毕。这正是Lock
用来解决的。 在上述代码中,Lock
对象互斥锁
的作用是确保在任何时候只能有一个进程占用厕所。而且,如果某个进程使用了Lock
,那么其他进程必须等待,直到前者释放Lock
后,剩下的进程才能继续争夺Lock
。
Semaphore
(信号量)也是一个非常有用的进程控制工具,尤其是在需要控制同时并发执行的场景中。与Lock
不同,Semaphore
允许多个进程同时执行,但它设定了同时并发的最大数目。
基本概念:
Semaphore
用于控制对共享资源的访问数量。Semaphore
。在多进程环境中,共享资源可能引发竞态条件或死锁。如果我们不采取措施,可能会出现资源被多个进程竞争读写,导致数据不一致或程序崩溃的情况。
不加锁的后果:
在下列示例中,如果三个进程同时运行,可以看到信息输出是混乱的,因为没有锁的保护,进程之间可能发生竞态条件。import multiprocessingimport timedef task1(): n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task1 输出信息") time.sleep(1) n -= 1def task2(): n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task2 输出信息") time.sleep(1) n -= 1def task3(): n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task3 输出信息") time.sleep(1) n -= 1if __name__ == '__main__': p1 = multiprocessing.Process(target=task1) p2 = multiprocessing.Process(target=task2) p3 = multiprocessing.Process(target=task3) p1.start() p2.start() p3.start()
为了避免竞态条件,我们可以在进程代码中加入锁机制。通过multiprocessing.Lock
对象确保只有一位进程能够同时运行。
关键点:
with
语句:我们可以将锁用with
语句包裹,这样lock
会自动管理上锁和下锁的过程。lock.acquire()
:在代码中显式地获取锁。lock.release()
:在操作完成后,释放锁,允许其他进程继续争夺锁。下面的实现对原先的代码进行了优化:
import multiprocessingimport timedef task1(lock): with lock: n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task1 输出信息") time.sleep(1) n -= 1def task2(lock): lock.acquire() n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task2 输出信息") time.sleep(1) n -= 1 lock.release()def task3(lock): lock.acquire() n = 4 while n > 1: print(time.strftime("%Y-%M-%d %H:%M:%S"), " task3 输出信息") time.sleep(1) n -= 1 lock.release()if __name__ == '__main__': lock = multiprocessing.Lock() p1 = multiprocessing.Process(target=task1, args=(lock,)) p2 = multiprocessing.Process(target=task2, args=(lock,)) p3 = multiprocessing.Process(target=task3, args=(lock,)) p1.start() p2.start() p3.start()
注意事项:
lock.acquire()
必须与lock.release()
对应,任何时候只能有一个进程占有锁。acquire()
,这会导致死锁。每次获取锁必须在解锁之后。与join
比较:
join
是人为设定顺序,而lock
是通过资源竞争来保证公平性,用户进程先到先得。结论:在多进程编程中,Lock
和Semaphore
是确保资源安全和避免竞态条件的重要工具。正确使用它们,可以显著提高程序的稳定性和效率。
转载地址:http://jbbwk.baihongyu.com/