博客
关于我
python---多进程并发控制 Semaphore 与 互斥锁 LOCK
阅读量:741 次
发布时间:2019-03-22

本文共 2569 字,大约阅读时间需要 8 分钟。

一、了解Lock

当我们编写多进程程序时,资源管理可能会遇到竞态条件或死锁问题。一个常见的解决方案是使用Lock。理解Lock的使用是掌握多进程编程的关键。

应用场景举例:

假设我们有一个厕所资源,只能供一位人使用。如果有多个进程同时请求使用这个资源,怎么办?我们需要确保只有一个人能使用厕所,其他人的请求必须等待处理完毕。这正是Lock用来解决的。

在上述代码中,Lock对象互斥锁的作用是确保在任何时候只能有一个进程占用厕所。而且,如果某个进程使用了Lock,那么其他进程必须等待,直到前者释放Lock后,剩下的进程才能继续争夺Lock


2、进程并发控制Semaphore

Semaphore(信号量)也是一个非常有用的进程控制工具,尤其是在需要控制同时并发执行的场景中。与Lock不同,Semaphore允许多个进程同时执行,但它设定了同时并发的最大数目。

基本概念:

  • Semaphore用于控制对共享资源的访问数量。
  • 同一时刻,只有预定数量的进程可以访问共享资源。
  • 超过这个数量的进程会在等待状态,直到有进程释放资源,也释放Semaphore

三、进程同步之LOCK

在多进程环境中,共享资源可能引发竞态条件或死锁。如果我们不采取措施,可能会出现资源被多个进程竞争读写,导致数据不一致或程序崩溃的情况。

不加锁的后果:

在下列示例中,如果三个进程同时运行,可以看到信息输出是混乱的,因为没有锁的保护,进程之间可能发生竞态条件。

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()

使用LOCK优化代码

为了避免竞态条件,我们可以在进程代码中加入锁机制。通过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是通过资源竞争来保证公平性,用户进程先到先得。

    结论:在多进程编程中,LockSemaphore是确保资源安全和避免竞态条件的重要工具。正确使用它们,可以显著提高程序的稳定性和效率。

    转载地址:http://jbbwk.baihongyu.com/

    你可能感兴趣的文章
    OpenCV与AI深度学习 | 实战 | OpenCV传统方法实现密集圆形分割与计数(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | OpenCV实现扫描文本矫正应用与实现详解(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | YOLOv10模型微调检测肾结石并提高准确率
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用OpenCV和Streamlit搭建虚拟化妆应用程序(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用OpenCV确定对象的方向(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用YOLOv8 Pose实现瑜伽姿势识别
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用YoloV8实例分割识别猪的姿态(含数据集)
    查看>>
    OpenCV与AI深度学习 | 实战 | 使用姿态估计算法构建简单的健身训练辅助应用程序
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于OpenCV和K-Means聚类实现颜色分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YoloV5和Mask RCNN实现汽车表面划痕检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9+SAM实现动态目标检测和分割(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 实战 | 文本图片去水印--同时保持文本原始色彩(附源码)
    查看>>
    OpenCV与AI深度学习 | 实战—使用YOLOv8图像分割实现路面坑洞检测(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战篇——基于YOLOv8和OpenCV实现车速检测(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战|OpenCV实时弯道检测(详细步骤+源码)
    查看>>
    OpenCV与AI深度学习 | 实用技巧 | 使用OpenCV进行模糊检测
    查看>>
    OpenCV与AI深度学习 | 实践教程|旋转目标检测模型-TensorRT 部署(C++)
    查看>>
    OpenCV与AI深度学习 | 工业缺陷检测中数据标注需要注意的几个事项
    查看>>
    OpenCV与AI深度学习 | 干货 | 深度学习模型训练和部署的基本步骤
    查看>>