今日内容
1、守护进程vs 守护线程(*)
2、互斥锁(**)
3、信号量(**)
4、生产者消费者模型(*****)
5、GIL(什么时候用进程,什么时候用线程)(*****)
一、守护进程和守护线程
1、守护进程 (分出去的进程设置成守护进程)
守护进程不能开启子进程
#守护进程 from multiprocessing import Process import os,time,random def task(): print("%s is running"%os.getpid()) time.sleep(2) print("%s is done"%os.getpid()) # p=Process(target=time.sleep,args=(3,)) # p.start() if __name__=="__main__": p=Process(target=task) p.daemon=True #1、 p.start() print("主")
举例说明守护进程的应用场景:
假设有两个任务要干,要玩出并发的效果,使用进程的话可以让主进程
执行一个任务,然后开启一个子进程执行一个任务。
如果这两个任务毫无关系,那么就像上面这么做就可以
如果主进程的任务在执行完毕后,子进程的任务没有存在的意义了
那么该子进程应该在开启之前就被设置成守护进程
# 迷惑人的例子 # 主进程代码运行完毕,守护进程就会结束 from multiprocessing import Process from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__=="__main__": p1=Process(target=foo) p2=Process(target=bar) # p1.daemon=True p1.start() p2.start() print("main___")# 打印该行则主进程代码结束,则守护进程p1应该被终止, # 可能会有p1任务执行的打印信息123,因为主进程打印main----时 # ,p1也执行了,但是随即被终止
总结 :主进程运行完毕,守护进程也会随之结束
2、守护线程
一个进程开启了多个线程
(1)守护线程能开启子线程
#守护线程:等到该进程内所有非守护线程都运行完才死掉 from multiprocessing import Process from threading import Thread import os,time,random def task(): t=Thread(target=time.sleep,args=(3,)) t.start() print("%s is running"% os.getpid()) time.sleep(2) print("%s is done"%os.getpid()) if __name__=="__main__": t=Thread(target=task) t.daemon=True #1、必须在t.start()之前2:守护线程可以开启子线程 t.start() t.join() print("主")
(2)迷惑人的例子 ————守护线程
其中非守护线程还没有结束(开启线程的目的是为了执行完毕函数)
#迷惑人的例子:守护线程 from multiprocessing import Process from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(2) print("end456") if __name__=="__main__": t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main_____") # 123 # 456 # main_____ # end123 # end456
3、总结:
为什么守护进程内不让开启子进程?
主进程结束之后守护线程就会死掉(在这个进程中所有的非守护线程都运行完)
主线程什么时候结束?
主进程死掉(所有的线程结束后) 接着守护进程就会死掉
二、互斥锁
1、互斥锁进程
from multiprocessing import Process,Lock import os,time,random def task(): print("%s print 1"%os.getpid()) time.sleep(random.randint(1,3)) print("%s print 2"%os.getpid()) time.sleep(random.randint(1, 3)) print("%s print 3" % os.getpid()) if __name__=="__main__": p1=Process(target=task) p2=Process(target=task) p3=Process(target=task) p1.start() p1.join() p2.start() p2.join() p3.start() p3.join()
from multiprocessing import Process,Lock import os,time,random def task(mutex): mutex.acquire() print("%s print 1"%os.getpid()) time.sleep(random.randint(1,3)) print("%s print 2"%os.getpid()) time.sleep(random.randint(1, 3)) print("%s print 3" % os.getpid()) mutex.release() if __name__=="__main__": # p1=Process(target=task) # p2=Process(target=task) # p3=Process(target=task) # p1.start() # p1.join() # p2.start() # p2.join() # p3.start() # p3.join() mutex=Lock() p1 = Process(target=task,args=(mutex,)) p2 = Process(target=task,args=(mutex,)) p3 = Process(target=task,args=(mutex,)) p1.start() p2.start() p3.start()
2、模拟抢票的例子
from multiprocessing import Process,Lock import json import os,time,random def search(): with open("db.txt",encoding="utf-8") as f: dic=json.load(f) print("%s 剩余票数%s"%(os.getpid(),dic["count"])) def get(): with open("db.txt",encoding="utf-8")as read_f: dic=json.load(read_f) if dic["count"]>0: dic["count"]-=1 time.sleep(random.randint(1,3))#模拟手速+网速 with open("db.txt","w",encoding="utf-8")as write_f: json.dump(dic,write_f) print("%s 抢票成功"%os.getpid()) def task(mutex): search() mutex.acquire() get() mutex.release() if __name__=="__main__": # for i in range(20): # p=Process(target=task) # p.start() # p.join() mutex=Lock() for i in range(20): p=Process(target=task,args=(mutex,)) p.start() p.join()
3、线程互斥锁
# 线程互斥锁 from threading import Thread,Lock import time n=100 def task(): global n with mutex: temp=n time.sleep(0.1) n=temp-1 if __name__=="__main__": mutex=Lock() t_1=[] for i in range(100): t=Thread(target=task) t_1.append(t) t.start() for t in t_1: t.join() print(n)
三、信号量(和进程池不一样)
例子:抢公共厕所(假如进去10个人,十把钥匙,结束一个就释放钥匙,然后进去一个)
1、进程的信号量:
from multiprocessing import Process,Semaphore # from threading import Thread,Semaphore import time,random,os def task(sm): with sm: print("%s 上厕所"%os.getpid()) time.sleep(random.randint(1,3)) if __name__=="__main__": sm=Semaphore(3) for i in range(10): for i in range(10): p=Process(target=task,args=(sm,)) p.start()
2、小心锁与锁之间的嵌套
(1)管道和队列都是用的内存的空间
(2)队列是基于管道加锁实现的
(3)如果对管道感兴趣就看博客 队列推荐使用
3、 进程Queue 和线程Queue
不能直接放视频,应该直接放路径或者是链接
(1)
from multiprocessing import Queue #进程队列 # import queue #线程队列 q=Queue(3) q.put({"a":1}) q.put("xxxxx") q.put(2) q.put(4) print(q.get()) print(q.get()) print(q.get()) print(q.get())
(2)队列的功能————先进先出
from multiprocessing import Queue #进程队列 import queue #线程队列 q=queue.Queue(3) q.put({"a":1}) q.put("xxxxx") q.put(2) q.put(4) print(q.get()) print(q.get()) print(q.get()) print(q.get())
# 优先级队列 from multiprocessing import Queue #进程队列 import queue #线程队列 q=queue.PriorityQueue(3) q.put((10,{"a":1})) q.put((-1,"xxxxx")) q.put((0,2)) print(q.get()) print(q.get()) print(q.get()) # (-1, 'xxxxx') # (0, 2) # (10, {'a': 1})
(3)堆栈————后进先出
# 堆栈 from multiprocessing import Queue #进程队列 import queue #线程队列 q=queue.LifoQueue(3) q.put({"a":1}) q.put("xxxxx") q.put(2) print(q.get()) print(q.get()) print(q.get()) print(q.get()) # 2 # xxxxx # {'a': 1}
四、生产者和消费者模型
模型指的概念
生产者消费者可以实现程序的解耦
from multiprocessing import Process,Queue import time,random,os def producer(q): for i in range(10): res="包子 %s"%i time.sleep((random.randint(1,3))) q.put(res) print("%s生产了%s"%(os.getpid(),res)) def consumer(q): while True: res=q.get() print("%s 吃 %s"%(os.getpid(),res)) time.sleep((random.randint(2,3))) if __name__=="__main__": q=Queue() p=Process(target=producer,args=(q,)) c=Process(target=consumer,args=(q,)) p.start() c.start() print("主") from multiprocessing import Process,Queue import time,random,os def procducer(q): for i in range(10): res="包子%s"%i time.sleep(0.5) q.put(res) print("%s生产了%s"%(os.getpid(),res))
线程要不要用生产者消费者模型
也要用队列来实现
from multiprocessing import Process,Queue import time,random,os def procducer(q): for i in range(10): res="包子%s"%i time.sleep(0.5) q.put(res) print("%s生产了%s"%(os.getpid(),res)) def consumer(q): while True: res=q.get() if res is None: break print("%s 吃 %s"%(os.getpid(),res)) time.sleep(random.randint(2,3)) if __name__=="__main__": q=Queue() p=Process(target=procducer,args=(q,)) c=Process(target=consumer,args=(q,)) p.start() c.start() p.join() q.put(None) print("主")