36 锁(lock), 信号(semaphore), 事件(event)

主要内容 :

1 . 锁机制 : 一把钥匙配一把锁

  实例化一个钥匙对象 : l = lock()

  拿钥匙 : l.acquire()

  取钥匙 : l.release()

 事例一 : 存钱取钱问题 

#存钱, 取钱        
from multiprocessing import Process, Value, Lock
import time  value: 由于数据不共享, 所以引入了value模块      
def get_money(num, l):
    l.acquire()          #拿走钥匙, 锁上门, 不让其他人进屋.
    for i in range(100):
        num.value = num.value - 1
        print(num.value)
    l.release()         #还钥匙, 打开门 , 其他人可以进屋.
def put_money(num, l):
    l.acquire()
    for i in range(100):
       num.value = num.value +1
       print(num.value)
    l.release()
if __name__ == '__main__':
    l = Lock()
    num = Value('i', 100)
    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)

   注意 :既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊  没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高.

  事例二 : 12306取票问题

def buy_ticket(i, l):
    l.acquire()
    with open('ticket1')as f:
        conn = f.read()
        conn = int(conn)
        time.sleep(0.1)       #模拟网络延迟.
    if conn > 0:
        print('33[31m 第%s个人买到票了 33[0m' % i)
        conn = conn - 1
    else:
        print('33[34m 第%s个人没有买到票 33[0m' % i)
    time.sleep(0.1)    # 买完票后, 把余票数据重写数据库的时间延迟.
    with open('ticket1', 'w') as f :
        f.write(str(conn))
    l.release()
if __name__ == '__main__':
    l = Lock()
    for i in range(10):
        p = Process(target=check_ticket, args=(i + 1,))
        p.start()
    for i in range(10):
        p1 = Process(target=buy_ticket, args=(i + 1, l))
        p1.start()

2 . 信号机制 : 一把锁可以配几把钥匙

  是指sem = Semaphore(n)

  n : 是指初始化一把锁配几把钥匙 , 一个int型

  信号量机制比锁机制多了一个计数器, 这个计数器是用来记录当前剩余几把钥匙的.每acquire一次,计数器内部减一, release一次, 计数器加一

from multiprocessing import Process, Semaphore
sem = Semaphore(2)     # 一把钥匙配两把锁
sem.acquire()          #拿走一把钥匙锁上门
print(123)
sem.acquire()          #拿走一把钥匙,锁上门
print(123)
sem.release()
sem.acquire()
print(123)

  事例一

from multiprocessing import Process, Semaphore
import time
import random
def func(i, sem):
    sem.acquire()
    print('第%s个人拿了, 钥匙,锁了门,' % i)
    time.sleep(random.randint(1,4))
    print('第%s个人还了, 钥匙,开了门,' % i)
    sem.release()
if __name__ == '__main__':
    sem = Semaphore(5)  
#初始化一把钥匙开五把锁, 可以同时5个人进入小黑屋, 之后其他人必须等待,等有人从小黑屋里出来,才允许后面的人进入.
    for i in range(6):
        p = Process(target=func,args=(i, sem))
        p.start()

3 . 事件机制

  e. event()

  e.set() :          将is_set()设为ture

  e.clear():        将is_set()设为false

  e.wait() :        判断is_set的布尔值, 如果布尔值为ture, 则非阻塞, 否则为false

  e.is_set():      标识

  事件通过is_set的bool值, 去标识e.wait()的阻塞状态

from multiprocessing import Process, Event
import time
def traffic_light(e):
    while 1:
        if e.is_set():    #ture 表示绿灯亮 , 此时wait为非阻塞状态,此时car进程在并行状态下可以执行
            time.sleep(5)    #执行5s钟
            print('红灯亮')  #显红灯
            e.clear()       #将is_set的值设为false
        else:
            time.sleep(5)  #程序从上到下执行,先执行else:因为类event的is_set的默认返回值是false, 先停5秒.
            print('绿灯亮') # 然后显示绿灯亮.
            e.set()   #将is_set的表示设为ture.
def car(i, e):
    e.wait()
    print('第%s辆车过去了' % i)
if __name__ == '__main__':
    e = Event()
    p_tra = Process(target=traffic_light, args=(e,))
    p_tra.start()
    for i in range(50):
        p_car = Process(target=car, args=(i + 1, e))
        p_car.start()

  

 

原文地址:https://www.cnblogs.com/gyh412724/p/9513031.html