lession11
一 守护进程
独立的进程
1 主进程会等待子进程结束,但是不等待守护进程结束,当主进程死亡后,等待子进程结束,不等待守护进程
from multiprocessing import Process
import time
import random
class Piao(Process):
def init(self,name):
self.name=name
super().init()
def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randrange(1,3))
print('%s is piao end' %self.name)
if name=="main":
p=Piao('egon')
p.daemon=True #一定要在p.start()前设置,设置p为守护进程,禁止p创建子进程,并且父进程代码执行结束,p即终止运行
p.start()
p1=Piao('egon')
p1.start()
print('主')
2 守护线程
1.对主进程来说,运行完毕指的是主进程代码运行完毕
2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
守护线程是保护当前进程中所有的线程。下面实例中保护所有线程结束后结束
1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,
2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
from threading import Thread
import time
def foo():
print(123)
time.sleep(1)
print(234)
def bar():
print(456)
time.sleep(2)
print(4567)
if name=="main":
t1 = Thread(target=foo)
t2 = Thread(target = bar)
t1.daemon = True
t1.start()
t2.start()
print("over")
3 互斥锁
lock 将 并行变成串行
虽然可以用文件共享数据实现进程间通信,但问题是:
1.效率低(共享数据基于文件,而文件是硬盘上的数据)
2.需要自己加锁处理
from multiprocessing import Process,Lock
import time,json,random,os
def search():
dic = json.load(open("db.txt"))
print("user {}".format(os.getpid()))
print(' 33[43m剩余票数%s 33[0m' % dic['count'])
def get():
dic = json.load(open("db.txt"))
time.sleep(0.1)
if dic["count"] > 0:
dic["count"] -= 1
time.sleep(0.2)
json.dump(dic,open('db.txt','w'))
print("user {}".format(os.getpid()))
print("success")
def task(lock):
search()
lock.acquire()
get()
lock.release()
if name == "main":
lock = Lock()
lock.release()
for i in range(100):
p = Process(target=task,args=(lock,))
p.start()
print(1111,p.pid)
生产者消费者模型总结
#程序中有两类角色
一类负责生产数据(生产者)
一类负责处理数据(消费者)
#引入生产者消费者模型为了解决的问题是:
平衡生产者与消费者之间的工作能力,从而提高程序整体处理数据的速度
#如何实现:
生产者<-->队列<——>消费者
#生产者消费者模型实现类程序的解耦和
为了解决进程退不出的问题
可以给queue中发送None 告知结束
互斥锁
互斥锁
from threading import Thread,Lock
import time
mutex = Lock()
n = 100
def task():
global n
with mutex:
temp = n
time.sleep(0.1)
n = temp -1
if name == "main":
t_1 = []
start_time = time.time()
for i in range(100):
t = Thread(target=task)
t_1.append(t)
t.start()
t.join()
for t in t_1:
t.join()
print(n)
print(time.time()-start_time)
import threading
import time
def haha(max_num):
for i in range(max_num):
time.sleep(1)
print(i)
time.sleep(3)
方法1
l = []
for x in range(3):
t=threading.Thread(target=haha,args=(5,))
t.start()
l.append(t)
t.join()
#通过join方法让线程逐条执行
print("ok")
start_time = time.time()
for x in l:
x.join()
print(time.time()-start_time)
GIL全局解释锁
我们有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程
单核情况下,分析结果:
如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜
多核情况下,分析结果:
如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行用不上多核,方案一胜
如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜 如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜
递归锁
进程池
线程池
concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用
submit 提交任务 是异步提交任务
from concurrent.futures import ProcessPoolExecutor
import os, time ,random
def task(n):
print("{} is running".format(os.getpid()))
time.sleep(random.randint(1,3))
return n ** 2
if name == "main":
p = ProcessPoolExecutor()
for i in range(10):
p.submit(task,i)