python 进程同步(锁LOCK,信号量Semaphore,事件Event),生产者消费模型

1.锁 —— multiprocessing.Lock  

当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

from multiprocessing import Process
import random
import time

def func(addr):
    print('我是%s'%addr)
    time.sleep(random.random())
    print('谢谢!')

if __name__ == '__main__':
    l = ['四川的','湖南的','河南的','江苏的']
    for addr in l:
        p = Process(target=func,args=(addr,))
        p.start()
    time.sleep(2)
    print('

我选%s'%random.choice(l))
# 关于抢占输出资源的事情,是指多进程并发执行时,并不是一个进程执行完任务后其他进程再执行。
# 比如 此程序会输出:我是四川的  我是河南的 我是江苏的 谢谢!谢谢!我是湖南的 谢谢! 谢谢!
# 而不是 : 我是四川的 谢谢! 我是河南的 谢谢! ...
多进程抢占资源
from multiprocessing import Process ,Lock
import random
import time

def func(addr,lock):
    lock.acquire()
    print('我是%s'%addr)
    time.sleep(random.random())
    print('谢谢!')
    lock.release()

if __name__ == '__main__':
    lock = Lock()
    l = ['四川的','湖南的','河南的','江苏的']
    for addr in l:
        p = Process(target=func,args=(addr,lock))
        p.start()
    time.sleep(4)
    print('

我选%s'%random.choice(l))
使用锁维护输出资源
from multiprocessing import Process,Lock
import time

def check(i):
    with open('a') as f :
        num = f.read()
    print('第%s个人在查票,余票为%s' % (i,num))

def buy(i,l):
    l.acquire()
    with open('a') as f :
        num = int(f.read())
        time.sleep(0.1)
    if num >0 :
        print('33[31m 第%s个人买到票了33[0m'%i)
        num -= 1
    else:
        print('33[32m 第%s个人没有买到票33[0m'%i)
    time.sleep(0.1)
    with open('a','w') as f :
        f.write(str(num))
    l.release()

if __name__ == "__main__" :
    l=Lock()
    for i in range(10):
        p_ch = Process(target=check,args=(i+1,))
        p_ch.start()
    for i in range(10):
        p_buy = Process(target=buy,args=(i+1,l))
        p_buy.start()
例:抢票
from multiprocessing import Process,Lock,Value
import time

def get_money(num,l):
    l.acquire()
    for i in range(100):
        num.value -=1
        print(num.value)
        time.sleep(0.01)
    l.release()

def put_money(num,l):
    l.acquire()
    for i in range(100):
        num.value+=1
        print(num.value)
        time.sleep(0.01)
    l.release()

if __name__ =='__main__':
    num =  Value('i',100)
    l = Lock()
    p = Process(target=get_money,args=(num,l))
    p.start()
    p1 = Process(target=put_money, args=(num,l))
    p1.start()
    p.join()
    p1.join()
    print(num.value)
例:银行存取钱

 2.信号量 —— multiprocessing.Semaphore(了解)      

上述讲的Lock,属于互斥锁,也就是一把钥匙配备一把锁,同时只允许锁住某一个数据。而信号量则是多把钥匙配备多把锁,也就是说同时允许锁住多个数据。

比如在一个粉红发廊,里边有5位服务人员,那么这个发廊最多就同时允许进入5位客人,当又有第6位客人来的时候,就需要在门外等待;当服务人员服务完某位客人后,才允许后续的人再进来一个,换句话说,这个发廊最多同时接待5位客人,多的客人必须等待。

信号量同步基于内部计数器,用户初始化一个计数器初值(比如上述例子中就初始化为5),每调用一次acquire(),计数器减1;每调用一次release(),计数器加1。当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念
from multiprocessing import Process,Semaphore
import time
import random

def func(i,sem):
    sem.acquire()
    print('第%s个人进入小黑屋,拿了钥匙锁上门' % i)
    time.sleep(random.randint(3,5))
    print('第%s个人出去小黑屋,还了钥匙打开门' % i)
    sem.release()
if __name__ == '__main__' :
    sem =Semaphore(5)
    for i in range(20) :
        p = Process(target=func,args=(i,sem))
        p.start()
例子

3.事件 —— multiprocessing.Event(了解)           

#from multiprocessing import Event

#e = Event()
# e.set()
# e.clear()
# e.wait()
# e.is_set()
# 事件是通过is_set()的bool值,去标识e.wait() 的阻塞状态
# 当is_set()的bool值为False时,e.wait()是阻塞状态
# 当is_set()的bool值为True时,e.wait()是非阻塞状态
# 当使用set()时,是把is_set的bool变为True
# 当使用clear()时,是把is_set的bool变为False
from multiprocessing import Event, Process
import time

def tra(e):
    while 1:
        if e.is_set():
            time.sleep(5)
            print('33[31m 红灯亮!33[0m')
            e.clear()
        else:
            time.sleep(5)
            print('33[32m 绿灯亮!33[0m')
            e.set()


def Car(i, e):
    e.wait()
    print('第%s辆车过去了' % i)



if __name__ == '__main__':
    e = Event()
    triff_light = Process(target=tra, args=(e,))
    triff_light.start()
    for i in range(500):
        car = Process(target=Car, args=(i + 1, e,))
        car.start()
        time.sleep(2)
例:交通信号灯

        

原文地址:https://www.cnblogs.com/beihan/p/9513632.html