#同一时间允许一个进程上一把锁 就是Lock
加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。
#同一时间允许多个进程上多把锁 就是[信号量Semaphore]
信号量是锁的变形: 实际实现是 计数器 + 锁,同时允许多个进程上锁
# 互斥锁Lock : 互斥锁就是进程的互相排斥,谁先抢到资源,谁就上锁改资源内容,为了保证数据的同步性
# 注意:多个锁一起上,不开锁,会造成死锁.上锁和解锁是一对.如下就会形成死锁
lock.acquire()
lock.acquire()
lock.release()
print(123)
(1)单个锁Lock
语法:
from multiprocessing import Process,Lock
lock = Lock() 实例化一把锁
lock.acquire() 上锁
lock.release() 解锁
例:现在模拟一个抢票程序,每次自允许一个人进行修改数据
1 # 假设现在有数据{"count":3},有3张票 2 import json 3 import time 4 from multiprocessing import Process, Lock 5 6 def search(person): 7 with open("ticket", mode="r") as fp: 8 dic = json.load(fp) 9 # print(dic,type(dic)) 10 print("%s 查询余票:%s" % (person, dic["count"])) 11 12 def get_ticket(person): 13 with open("ticket", mode="r") as fp: 14 dic = json.load(fp) 15 time.sleep(0.5) 16 if dic["count"] > 0: 17 print("%s买到了" % (person)) 18 dic["count"] -= 1 19 # 重新更新数据库 20 with open("ticket", "w") as fp: 21 json.dump(dic, fp) 22 else: 23 print("%s没买到这个票" % (person)) 24 25 26 # 作为统一的并发调用 27 def ticket(person, lock): 28 # 查询票数 29 search(person) 30 # 上锁 到上锁的时候是同步程序 31 lock.acquire() # 上锁 32 get_ticket(person) 33 lock.release() # 解锁 34 35 36 if __name__ == "__main__": 37 lock = Lock() 38 for i in range(10): 39 # 这里是异步并发 40 p = Process(target=ticket, args=("person%s" % i, lock)) 41 p.start()
#执行结果 person2 查询余票:3 person1 查询余票:3 person3 查询余票:3 person0 查询余票:3 person4 查询余票:3 person6 查询余票:3 person9 查询余票:3 person7 查询余票:3 person8 查询余票:3 person5 查询余票:3 person2买到了 person1买到了 person3买到了 person0没买到这个票 person4没买到这个票 person6没买到这个票 person9没买到这个票 person7没买到这个票 person8没买到这个票 person5没买到这个票
(2)多个锁Semaphore
语法:
from multiprocessing import Process,Semaphore
sem = Semaphore(4) 可以传参,指定多把锁
sem.acquire() 上锁
sem.release() 解锁
例:模拟ktv唱歌 假设一共10个人,同一时间允许4个人唱歌
from multiprocessing import Process,Semaphore import random,time def ktv(person,sem): sem.acquire() print("%s进入了ktv" % (person)) time.sleep(random.randrange(6,8)) print("%s走出了ktv" % (person)) sem.release() if __name__ == "__main__": # 最多允许4个进程同时上锁 sem = Semaphore(4) for i in range(10): p = Process(target=ktv,args=("person%s" % (i),sem)) p.start()
person0进入了ktv
person1进入了ktv
person2进入了ktv
person3进入了ktv
person0走出了ktv
person4进入了ktv
person2走出了ktv
person6进入了ktv
person3走出了ktv
person5进入了ktv
person1走出了ktv
person7进入了ktv
person4走出了ktv
person8进入了ktv
person6走出了ktv
person9进入了ktv
person5走出了ktv
person7走出了ktv
person8走出了ktv
person9走出了ktv