首页 > 系统相关 >进程间的锁和信号量

进程间的锁和信号量

时间:2023-07-23 18:33:13浏览次数:32  
标签:__ Lock Worker 信号量 Semaphore 进程 multiprocessing

multiprocessing模块中,可以使用Lock(锁)来实现进程间的同步。Lock提供了一种机制,确保在任意时刻只有一个进程能够访问共享资源。

Lock的工作原理

Lock是一种互斥锁,用于保护共享资源的访问。当一个进程获得了锁之后,其他进程将被阻塞,直到锁被释放。只有释放锁的进程才能继续访问共享资源。

Lock的最佳实践

  1. 创建Lock对象:在创建Lock对象时,无需指定参数,使用默认值即可。

  2. 获取和释放锁:进程在需要访问受Lock保护的共享资源之前,必须先通过调用acquire()方法获取锁。访问完成后,必须通过调用release()方法释放锁。

  3. 处理异常情况:在使用Lock时,可能会出现超时或中断等异常情况。为了保证程序的稳定性,应该在适当的地方捕获并处理这些异常。

  4. 确保锁的释放:在编写代码时,需要确保每次获取到的锁都能被正确地释放。否则,可能会导致其他进程一直处于阻塞状态。

  5. 避免死锁:使用多个锁时,需要避免死锁的风险。死锁通常发生在多个进程相互等待对方释放资源的情况下。为了避免死锁,需要仔细设计和管理资源的获取和释放顺序,以及合理地使用锁。

Lock的坑

  1. 死锁的风险:使用多个锁时,需要避免死锁的风险。死锁通常发生在多个进程相互等待对方释放资源的情况下。为了避免死锁,需要仔细设计和管理资源的获取和释放顺序,以及合理地使用锁。

  2. 锁的性能开销:获取和释放锁会带来一定的性能开销。在使用锁时,需要权衡并考虑性能问题,避免过度使用锁导致性能下降。

示例

'''
multiprocessing 提供了锁(Lock)、信号量(Semaphore)等同步原语,用于实现进程间的互斥和同步。
可以使用这些同步原语来保护共享资源,防止多个进程同时访问造成数据竞争
'''
from multiprocessing import Process, Lock


def worker(lock):
    with lock: # 上锁,with会自动解锁
        print("This is a critical section")


if __name__ == '__main__':
    lock = Lock()  # 创建1个锁对象

    processes = []
    for _ in range(4):
        p = Process(target=worker, args=(lock,))  # 把锁传递给子进程们,让其上锁、解锁
        p.start()
        processes.append(p)
    # 主进程等待子进程结束
    for p in processes:
        p.join()

'''
输出:
    This is a critical section
    This is a critical section
    This is a critical section
    This is a critical section
'''
 1 from multiprocessing import Process, Lock
 2 
 3 
 4 def worker(lock, id):
 5     # 获取锁
 6     lock.acquire()
 7     try:
 8         print(f"Worker {id} is working")
 9     except:
10         print("捕获所有异常,避免上传传递")
11     finally:
12         # 释放锁
13         lock.release()
14         print(f"Worker {id} finished")
15 
16 
17 if __name__ == '__main__':
18     # 创建一个Lock对象
19     lock = Lock()
20 
21     processes = []
22     for i in range(5):
23         p = Process(target=worker, args=(lock, i))  # 创建进程
24         processes.append(p)
25         p.start()
26     # 主进程,等待子进程的结束(主进程阻塞)
27     for p in processes:
28         p.join()
29 
30 '''
31 输出:
32     Worker 0 is working
33     Worker 0 finished
34     Worker 1 is working
35     Worker 1 finished
36     Worker 2 is working
37     Worker 2 finished
38     Worker 3 is working
39     Worker 3 finished
40     Worker 4 is working
41     Worker 4 finished
42 
43 '''

 

信号量

multiprocessing模块中,由于进程之间的内存空间是独立的,所以不能直接使用Python标准库中的threading.Semaphore。不过可以通过使用multiprocessing.Manager来创建一个进程间共享的Semaphore对象

multiprocessing中的Semaphore工作原理

multiprocessing中,可以使用multiprocessing.Manager创建一个进程间共享的Semaphore对象。Semaphore的工作原理与标准库中的相同,用于控制对共享资源的访问。

multiprocessing中的Semaphore最佳实践

  1. 使用multiprocessing.Manager:在使用Semaphore时,需要使用multiprocessing.Manager来创建一个进程间共享的Semaphore对象。

  2. 获取和释放许可证:进程在需要访问受Semaphore保护的共享资源之前,必须先通过调用acquire()方法获取一个许可证。访问完成后,必须通过调用release()方法释放许可证。

  3. 处理异常情况:在使用Semaphore时,可能会出现超时或中断等异常情况。为了保证程序的稳定性,应该在适当的地方捕获并处理这些异常。

  4. 确保许可证被释放:在编写代码时,需要确保每个获取到的许可证都能被正确地释放。否则,可能会导致其他进程无法获取许可证而陷入阻塞状态。

  5. 关闭Manager:在程序结束后,应该显式地关闭Manager来释放资源。

multiprocessing中的Semaphore

  1. 进程间通信开销:由于进程之间的内存空间是独立的,所以进程间通信会带来一定的开销。在使用multiprocessing.Manager创建的Semaphore对象时,要注意控制进程间通信的频率和数据量,以避免性能问题。

  2. 异常处理:在使用Semaphore时,可能会出现超时或中断等异常情况。为了保证程序的稳定性,应该在适当的地方捕获并处理这些异常,避免阻塞或异常传播到整个系统。

示例

 1 from multiprocessing import Process, Manager
 2 
 3 
 4 def worker(semaphore, id):
 5     # 获取许可证
 6     semaphore.acquire()
 7     try:
 8         print(f"Worker {id} is working")
 9     except:
10         print("处理所有的异常")
11     finally:
12         # 释放许可证
13         semaphore.release()
14         print(f"Worker {id} finished")
15 
16 
17 if __name__ == '__main__':
18     with Manager() as manager:
19         # 创建一个进程间共享的Semaphore对象
20         semaphore = manager.Semaphore(2)
21 
22         processes = []
23         for i in range(5):
24             p = Process(target=worker, args=(semaphore, i))
25             processes.append(p)
26             p.start()
27 
28         for p in processes:
29             p.join()

输出:

Worker 0 is working
Worker 0 finished
Worker 1 is working
Worker 1 finished
Worker 2 is working
Worker 2 finished
Worker 3 is working
Worker 3 finished
Worker 4 is working
Worker 4 finished

使用multiprocessing.Manager创建了一个进程间共享的Semaphore对象 semaphore。然后,我们定义了一个 worker() 函数作为进程的任务函数。在 worker() 函数内部,首先通过 semaphore.acquire() 获取一个许可证,表示该进程开始占用资源。然后,打印一条工作信息,并最终通过 semaphore.release() 释放许可证,表示该进程结束占用资源。

在主程序中,我们创建了5个进程并启动它们,每个进程都会执行 worker() 函数。由于初始许可证数量为2,所以最多只有两个进程可以同时执行工作。其他进程会在调用 semaphore.acquire() 处阻塞,直到有可用的许可证。最后,我们使用 p.join() 等待所有进程执行完毕。

通过Semaphore的控制,我们可以限制同时访问共享资源的进程数量,从而避免资源的竞争和冲突。

标签:__,Lock,Worker,信号量,Semaphore,进程,multiprocessing
From: https://www.cnblogs.com/allenxx/p/17575481.html

相关文章

  • 进程池
    '''multiprocessing还提供了进程池(Pool)的功能,可以方便地管理一组工作进程。进程池中的多个进程可以被重复使用,以执行多个任务,并在完成任务后自动回收进程。'''frommultiprocessingimportPooldefworker(x):returnx*xif__name__=='__main__':#创建了......
  • 进程间通信
    说明进程间除了主子进程共享数据,也可以通过进程间通信实现交互、数据共享multiprocessing提供了多种方式来实现进程间通信,如管道(Pipe)、队列(Queue)和共享内存(Value和Array)等。通过这些机制,不同进程之间可以安全地共享数据或进行通信 队列(Queue)frommultiprocessingimpor......
  • 创建进程
    创建进程步骤1.导入进程包importmultiprocessing2.通过进程类创建进程对象进程对象=multiprocessing.Process()#是Process类3.启动进程执行任务进程对象.start() 示例1#1.导入多进程模块2importmultiprocessi......
  • android 双进程保活
    Android双进程保活在Android应用开发中,为了提供更好的用户体验,保证应用的稳定性和持久运行,我们常常需要保持应用进程的活跃状态。其中,双进程保活是一种常用的方式,本文将介绍如何通过双进程保活来实现应用的长时间运行。什么是双进程保活双进程保活是指通过启动一个后台进程来保......
  • 进程实现多任务(进程概念、单进程、多进程执行多任务)
    在Python程序中,想要实现多任务可以使⽤进程来完成,进程是实现多任务的⼀种⽅式。属于CPU密集型的任务。进程的概念进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位 ⼀个正在运⾏的程序或者软件至少有⼀个进程,也就是说每启动⼀个进程,操作系统都......
  • windows是使用命令kill进程
    参考:https://blog.csdn.net/zaizuxuan/article/details/126950788根据进程名找到进程例如python进程PSC:\Users\27467>tasklist|findstrpythonpython.exe7088Console23,364Kpython.exe1580Cons......
  • tivation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。
    困扰我大半年的错误,今天偶然间被解决了,特此分享给被同样问题纠结的朋友们!之前的求助帖,无人应答:http://www.cnblogs.com/freeton/archive/2012/08/28/2660585.htmlhttp://bbs.csdn.net/topics/391988642症状日志中大量报错,IIS严重错误,此类错误默认情况下5分钟连续出现5次会......
  • php与 redis的队列 && 如何守护进程?
    在PHP中,使用队列可以解决以下情况下的一些常见问题:异步任务处理:当应用程序需要处理一些耗时的任务,如发送电子邮件、生成报表、处理文件上传等,可以将这些任务添加到队列中,并使用队列进行异步处理,从而不影响主要的用户请求处理。消息通信:在分布式系统或微服务......
  • 向进程发送信号
    如果我们写了一个程序,监听特定信号,完成某些动作,如何向进程发送这个系统信号呢。kill-SIGUSR11234向进程id是1234的发送SIGUSR1信号kill并不是杀死某个进程,只不过默认会发送一些中断信号,也可以通过它发送一些其他信号。具体有哪些信号,也可以通过kill查询。......
  • Linux 网络基础 2 三次握手 三次挥手 多进程 多线程服务器
    1.包裹函数对服务器客户端等函数进行报错处理以及简化处理比如bindinttcp4bind(shortport,constchar*IP){structsockaddr_inserv_addr;intlfd=Socket(AF_INET,SOCK_STREAM,0);bzero(&serv_addr,sizeof(serv_addr));if(IP==NULL){//......