python实现多进程并发控制Semaphore与互斥锁LOCK

一、了解锁

应用场景举例描述: Lock 互斥锁:举例说明–有三个同事同时需要上厕所,但是只有一间厕所,将同事比作进程,多个进程并打抢占一个厕所,我们要保证顺序优先, 一个个来,那么就必须串行,先到先得,有人使用了,就锁住,结束后剩余的人继续争抢

1、利用Lock来处理

模拟三个同事抢占厕所

from multiprocessing import Process
from multiprocessing import Lock
import time
import random

def task1(p, lock):
    # 上锁
    lock.acquire()
    print(f'{p} 开始排泄')
    time.sleep(random.randint(1, 3))
    print(f'{p} 排泄结束')
    # 解锁
    lock.release()

def task2(p, lock):
    lock.acquire()
    print(f'{p} 开始排泄')
    time.sleep(random.randint(1, 3))
    print(f'{p} 排泄结束')
    lock.release()

def task3(p, lock):
    lock.acquire()
    print(f'{p} 开始排泄')
    time.sleep(random.randint(1, 3))
    print(f'{p} 排泄结束')
    lock.release()

if __name__ == '__main__':
    # 实例化一个锁对象
    mutex = Lock()
    # 将锁以参数的形式传入进程对象
    p1 = Process(target=task1, args=('task1', mutex,))
    p2 = Process(target=task2, args=('task2', mutex,))
    p3 = Process(target=task3, args=('task3', mutex,))

    p1.start()
    p2.start()
    p3.start()

执行结果:

# 输出结果:三个进程开始争抢互斥锁,先抢到的先执行,执行结束后,释放掉锁,剩下的继续争抢
task1 开始排泄
task1 排泄结束
task2 开始排泄
task2 排泄结束
task3 开始排泄
task3 排泄结束

1、 注意:

  • 互斥锁在函数中,lock.acquire()上锁一次就要lock.release()解锁一次,在上锁与解锁之间写需要执行的代码。
  • 如果连续上锁两次以上,就会出现死锁现象,代码将不继续执行下去。必须是锁一次解一次。

2、 lock和join比较:

  • 共同点------都可以把并行变成串行,保证了执行顺序
  • 不同点------join是人为设定了顺序,lock是让其争抢顺序,保证了公平性

2、利用反射,来优化上面的代码

上面的代码虽然起到了先进先出,一进一出的效果,但是并不完美。总所周知,我们上厕所是谁先抢到谁先上,并不是说按照代码里start()顺序执行。应该由先抢占到的进程限制性才更合理。

from multiprocessing import Process
from multiprocessing import Lock
import time
import random
import sys

def task1(p, lock):
    # 上锁
    lock.acquire()
    print(f'{p} 开始打印')
    time.sleep(random.randint(1, 3))
    print(f'{p} 打印结束')
    # 解锁
    lock.release()

def task2(p, lock):
    lock.acquire()
    print(f'{p} 开始打印')
    time.sleep(random.randint(1, 3))
    print(f'{p} 打印结束')
    lock.release()

def task3(p, lock):
    lock.acquire()
    print(f'{p} 开始打印')
    time.sleep(random.randint(1, 3))
    print(f'{p} 打印结束')
    lock.release()

if __name__ == '__main__':
    slock = Lock()
    for i in range(1,4):
       p = Process(target=getattr(sys.modules[__name__], f'task{i}'), args=(f'task{i}', slock))
       p.start()

输出结果:

task2 开始打印
task2 打印结束
task3 开始打印
task3 打印结束
task1 开始打印
task1 打印结束

二、进程并发控制 semaphore

semaphore(信号量):用来控制对共享资源的访问数量,可以控制同一时刻并发的进程数
信号量: 也是一把锁,但是不保证数据安全性,同时开启多个线程,但是规定了同时并发执行的上限,后面走多少,进多少。(用于控制并发数量)

1.多进程控制示例(1)

# 举例说明:一间厕所有5个坑位,最多只能同时有5个人上厕所,当前时刻有20个人想上厕所,但是只能让5个人进去,然后出来多少个,才能进去多少个上厕所

# 从一个模块引用多个功能的时候,用逗号隔开
from threading import Semaphore, Thread, currentThread
import time
import random

sem = Semaphore(3)             # 并发执行数设置为5

def task():
    sem.acquire()
    print(f'{currentThread().name}')
    time.sleep(random.randint(1,3))
    sem.release()

if __name__ == '__main__':
    for i in range(20):
        t = Thread(target=task)
        t.start()

执行结果:首次并发量是3,后面先抢到锁先执行

Thread-1
Thread-2
Thread-3

Thread-4
Thread-5

Thread-6
Thread-7

Thread-8

Process finished with exit code 0

2.多进程控制示例(2)

import multiprocessing
import time

def worker(s, i):
    s.acquire()
    print(time.strftime('%Y-%m-%d %H:%M:%S'), multiprocessing.current_process().name + " 抢占并获得锁,运行")
    time.sleep(i)
    print(time.strftime('%Y-%m-%d %H:%M:%S'), multiprocessing.current_process().name + " 运行结束,释放锁")
    s.release()

if __name__ == '__main__':
    s = multiprocessing.Semaphore(2)
    for i in range(8):
        p = multiprocessing.Process(target=worker, args=(s, 1))
        p.start()

执行结果:

在执行结果输出的终端,每阻塞一次,按下回车键,可以更加清晰的看出进程的并发执行。
由下面执行结果可以看出,同一时刻,有两个进程在执行
2021-05-18 22:50:37 Process-1 抢占并获得锁,运行
2021-05-18 22:50:37 Process-2 抢占并获得锁,运行

2021-05-18 22:50:38 Process-1 运行结束,释放锁
2021-05-18 22:50:38 Process-3 抢占并获得锁,运行
2021-05-18 22:50:38 Process-2 运行结束,释放锁
2021-05-18 22:50:38 Process-4 抢占并获得锁,运行

2021-05-18 22:50:39 Process-3 运行结束,释放锁
2021-05-18 22:50:39 Process-5 抢占并获得锁,运行
2021-05-18 22:50:39 Process-4 运行结束,释放锁
2021-05-18 22:50:39 Process-6 抢占并获得锁,运行

2021-05-18 22:50:40 Process-5 运行结束,释放锁
2021-05-18 22:50:40 Process-7 抢占并获得锁,运行
2021-05-18 22:50:40 Process-6 运行结束,释放锁
2021-05-18 22:50:40 Process-8 抢占并获得锁,运行

2021-05-18 22:50:41 Process-7 运行结束,释放锁
2021-05-18 22:50:41 Process-8 运行结束,释放锁

Process finished with exit code 0

三、进程同步之LOCK

多个进程并发执行,提高资源利用率,从而提高效率,但是有时候我们需要在某一时刻只能有一个进程访问某个共享资源的话,就需要使用锁LOCK

1.不加LOCK的示例

import multiprocessing
import time

def task1():
    n = 4
    while n > 1:
        print(f'{time.strftime("%Y-%M-%d %H:%M:%S")}  task1 输出信息')
        time.sleep(1)
        n -= 1

def task2():
    n = 4
    while n > 1:
        print(f'{time.strftime("%Y-%M-%d %H:%M:%S")}  task2 输出信息')
        time.sleep(1)
        n -= 1

def task3():
    n = 4
    while n > 1:
        print(f'{time.strftime("%Y-%M-%d %H:%M:%S")}  task3 输出信息')
        time.sleep(1)
        n -= 1

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task1)
    p2 = multiprocessing.Process(target=task2)
    p3 = multiprocessing.Process(target=task3)
    p1.start()
    p2.start()
    p3.start()

执行结果:

2021-59-18 22:59:46  task1 输出信息
2021-59-18 22:59:46  task2 输出信息
2021-59-18 22:59:46  task3 输出信息

2021-59-18 22:59:47  task1 输出信息
2021-59-18 22:59:47  task2 输出信息
2021-59-18 22:59:47  task3 输出信息

2021-59-18 22:59:48  task1 输出信息
2021-59-18 22:59:48  task2 输出信息
2021-59-18 22:59:48  task3 输出信息

Process finished with exit code 0

2.加上LOCK的示例

有两种加锁方式:首先将 lock = multiprocessing.Lock() 生成锁对象lock

  1. with lock: with会在执行前启动lock,在执行结束后关闭lock
  2. lock.acquire() … lock.release() : 注意,这俩必须是一个接一个的对应关系
import multiprocessing

import time

def task1(lock):
    with lock:
        n = 4
        while n > 1:
            print(f'{time.strftime("%Y-%M-%d %H:%M:%S")}  task1 输出信息')
            time.sleep(1)
            n -= 1

def task2(lock):
    lock.acquire()
    n = 4
    while n > 1:
        print(f'{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(f'{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()

执行结果

2021-11-18 23:11:37  task1 输出信息

2021-11-18 23:11:38  task1 输出信息

2021-11-18 23:11:39  task1 输出信息

2021-11-18 23:11:40  task2 输出信息

2021-11-18 23:11:41  task2 输出信息

2021-11-18 23:11:42  task2 输出信息

2021-11-18 23:11:43  task3 输出信息

2021-11-18 23:11:44  task3 输出信息

2021-11-18 23:11:45  task3 输出信息

Process finished with exit code 0

到此这篇关于python实现多进程并发控制Semaphore与互斥锁LOCK的文章就介绍到这了,更多相关python 多进程Semaphore与LOCK内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python多线程同步Lock、RLock、Semaphore、Event实例

    一.多线程同步 由于CPython的python解释器在单线程模式下执行,所以导致python的多线程在很多的时候并不能很好地发挥多核cpu的资源.大部分情况都推荐使用多进程. python的多线程的同步与其他语言基本相同,主要包含: Lock & RLock :用来确保多线程多共享资源的访问. Semaphore : 用来确保一定资源多线程访问时的上限,例如资源池.  Event : 是最简单的线程间通信的方式,一个线程可以发送信号,其他的线程接收到信号后执行操作. 二.实例 1)Lock &a

  • Python多进程同步Lock、Semaphore、Event实例

    同步的方法基本与多线程相同. 1) Lock 当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突. 复制代码 代码如下: import multiprocessing import sys def worker_with(lock, f):     with lock:         fs = open(f,"a+")         fs.write('Lock acquired via with\n')         fs.close()         def

  • python实现多进程并发控制Semaphore与互斥锁LOCK

    一.了解锁 应用场景举例描述: Lock 互斥锁:举例说明–有三个同事同时需要上厕所,但是只有一间厕所,将同事比作进程,多个进程并打抢占一个厕所,我们要保证顺序优先, 一个个来,那么就必须串行,先到先得,有人使用了,就锁住,结束后剩余的人继续争抢 1.利用Lock来处理 模拟三个同事抢占厕所 from multiprocessing import Process from multiprocessing import Lock import time import random def task

  • Python实现的多线程同步与互斥锁功能示例

    本文实例讲述了Python实现的多线程同步与互斥锁功能.分享给大家供大家参考,具体如下: #! /usr/bin/env python #coding=utf-8 import threading import time ''' #1.不加锁 num = 0 class MyThread(threading.Thread): def run(self): global num time.sleep(1) #一定要sleep!!! num = num + 1 msg = self.name + '

  • Python的互斥锁与信号量详解

    并发与锁 多个线程共享数据的时候,如果数据不进行保护,那么可能出现数据不一致现象,使用锁,信号量.条件锁 互斥锁 1. 互斥锁,是使用一把锁把代码保护起来,以牺牲性能换取代码的安全性,那么Rlock后 必须要relase 解锁 不然将会失去多线程程序的优势 2. 互斥锁的基本使用规则: import threading # 声明互斥锁 lock=threading.Rlock(); def handle(sid):# 功能实现代码 lock.acquire() #加锁 # writer code

  • Python多线程中阻塞(join)与锁(Lock)使用误区解析

    关于阻塞主线程 join的错误用法 Thread.join() 作用为阻塞主线程,即在子线程未返回的时候,主线程等待其返回然后再继续执行. join不能与start在循环里连用 以下为错误代码,代码创建了5个线程,然后用一个循环激活线程,激活之后令其阻塞主线程. threads = [Thread() for i in range(5)] for thread in threads: thread.start() thread.join() 执行过程: 1. 第一次循环中,主线程通过start函

  • Python解析器Cpython的GIL解释器锁工作机制

    目录 本节重点 一 引子 二 GIL介绍 三 GIL与Lock 四 GIL与多线程 五 多线程性能测试 本节重点 掌握Cpython的GIL解释器锁的工作机制 掌握GIL与互斥锁 掌握Cpython下多线程与多进程各自的应用场景 本节时长需控制在45分钟内 一 引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing

  • python并发编程多进程 互斥锁原理解析

    运行多进程 每个子进程的内存空间是互相隔离的 进程之间数据不能共享的 互斥锁 但是进程之间都是运行在一个操作系统上,进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端, 是可以的,而共享带来的是竞争,竞争带来的结果就是错乱 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import time def task(name): print("%s 1" % name) time.

  • Python编程中Python与GIL互斥锁关系作用分析

    我们知道,在 CPython 中,有一个全局解释器锁,英文叫 global interpreter lock,简称 GIL,是一个互斥锁,用来保护 Python 世界里的对象,防止同一时刻多个线程执行 Python 的字节码,从而确保线程安全,这导致了 Python 的线程无法利用多核 CPU 的优势,因此有人说 Python 的多线程是伪多线程,性能不高,那么 Python 将来有可能去除 GIL 吗? 要回答这个问题,先从 GIL 的起源进行分析. GIL 的起源 Python 第一次发布是

  • 举例讲解Python中的死锁、可重入锁和互斥锁

    一.死锁 简单来说,死锁是一个资源被多次调用,而多次调用方都未能释放该资源就会造成死锁,这里结合例子说明下两种常见的死锁情况. 1.迭代死锁 该情况是一个线程"迭代"请求同一个资源,直接就会造成死锁: import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = se

  • Python多线程编程(四):使用Lock互斥锁

    前面已经演示了Python:使用threading模块实现多线程编程二两种方式起线程和Python:使用threading模块实现多线程编程三threading.Thread类的重要函数,这两篇文章的示例都是演示了互不相干的独立线程,现在我们考虑这样一个问题:假设各个线程需要访问同一公共资源,我们的代码该怎么写? 复制代码 代码如下: ''' Created on 2012-9-8   @author: walfred @module: thread.ThreadTest3 '''  impor

  • 对python多线程中互斥锁Threading.Lock的简单应用详解

    一.线程共享进程资源 每个线程互相独立,相互之间没有任何关系,但是在同一个进程中的资源,线程是共享的,如果不进行资源的合理分配,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为"线程不安全". 实例如下: #-*- coding: utf-8 -*- import threading import time def test_xc(): f = open("test.txt","a") f.write("test_dxc&quo

随机推荐