锁——multiprocess.Lock:
加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,会牺牲了速度却保证了数据安全。
虽然可以用文件共享数据实现进程间通信,但问题是:
1,效率低。2,需要自己加锁处理。
multiprocess模块为我们提供的基于消息的IPC通信机制:队列和管道。
队列和管道都是将数据存放于内存中:
队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,我们应该避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可扩展性。
import os import time import random from multiprocessing import Lock from multiprocessing import Process def work(n,lock): lock.acquire() print('%s:%s is running' % (n,os.getpid())) time.sleep(random.random()) print('%s:%s is done' % (n,os.getpid())) lock.release() if __name__ == '__main__': lock = Lock() for i in range(10): p = Process(target=work,args=(i,lock)) p.start() # 同步控制 # 只要用到了锁,锁之内的代码就会变成同步的了 # 锁:控制一段代码,同一时间 只能被一个进程执行
import json import time import random from multiprocessing import Lock from multiprocessing import Process def check_ticket(i): with open('ticket') as f: ticket_count = json.load(f) # 通过json获取文件中的信息 print('person%s查询当前余票:'% i, ticket_count['count']) def buy_ticket(i,lock): check_ticket(i) # 先进行查票操作 lock.acquire() # 得到钥匙,进入程序 with open('ticket') as f: ticket_count = json.load(f) # 这一步是为了再次判断是否还有余票 time.sleep(random.random()) if ticket_count['count']>0: print('person%s购票成功'% i) ticket_count -= 1 # 字典的赋值 else: print('余票不足,person%s购票失败'% i) time.sleep(random.random()) with open('ticket','w')as f: json.dump(ticket_count,f) # 通过json.dump将字典转化成字符串形式,然后写入文件。 lock.release() # 归还钥匙 if __name__ == '__main__': lock = Lock() for i in range(10): Process(target=buy_ticket,args = (i,lock)).start()
信号量——multiprocess.Semaphore(了解)
互斥锁同时只允许一个线程更爱数据,而信号量Semaphore是同时允许一定数量的线程更改数据。
信号量同步基于内部计数器,每调用一次acquire(),计数器减1,每调用一次release(),计数器加1,当计数器为0时,acquire()调用被阻塞,这是迪科斯彻信号量概念p()和v()的python实现,信号量同步机制适用于访问像服务器这样的有限资源。
信号量与进程池的概念很像,但是要区分开,信号量涉及到枷锁的概念。
import time import random from multiprocessing import Process from multiprocessing import Semaphore def ktv(i,sema): sema.acquire() print('person%s 进来唱歌了'% i) time.sleep(random.randint(1,5)) print('person%s 从ktv出去了'% i) sema.release() if __name__ == '__main__': sema = Semaphore(3) for i in range(5): Process(target=ktv,args=(i,sema)).start() # Semaphore 就是锁+计数器 # acquire() 计数器-1 # release() 计数器+1 # 当计数器为0,acquire()就会阻塞
事件——multiprocess.Event (了解)
python线程的时间用于主线程控制其他线程的执行,事件主要提供了三个方法:set(),wait(),clear().
事件处理的机制,全局定义了一个flag,如果flag值为False,那么当程序执行,event.wait()方法时就会阻塞,如果flag值为True,那么event.wait 方法时便不再阻塞。
clear:将flag设置为False.
set:将flag设置为True.
import time import json import random from multiprocessing import Event from multiprocessing import Process def car(i,e): if not e.is_set(): print('car%s正在等待'% i) e.wait() print('car%s正在通过'% i) def traffic_light(e): print('