2.主进程正常结束,子进程与主进程一并被回收资源。
from multiprocessing import Processimport timedef task(): print('start...') time.sleep(2) print('end...')if __name__ == '__main__': p = Process(target=task) p.start() p.join() #不加join会先不等待子进程,主进程先回收 print('主进程结束')
2.僵尸进程与孤儿进程:
僵尸进程:
在子进程结束后,主进程没有正常结束,子进程PID不会被回收。
缺点:
1.操作系统中的pid是有限的,如果子进程pid号无法正常回收,则会占用pid号
2.浪费资源
3.若pid号满了,则无法创建新的进程。
孤儿进程:
在子进程没有结束的时候主进程没有正常结束,子进程不会被会回收。
操作系统优化机制(孤儿院)
当主进程意外终止,操作系统会检测是否有正在运行的子进程,会将他们放入孤儿院中,让操纵系统帮你自动回收。
from multiprocessing import Processfrom multiprocessing import current_process #查看进程idimport osimport timedef task(): print(f'start...{current_process().pid}') time.sleep(5) print(f'end.....{os.getpid()}') print('子进程结束')if __name__ == '__main__': p = Process(target=task) p.start() print(f'进入主进程的io--{current_process().pid}') time.sleep(2) print(f'进入主进程的IO--{os.getpid()}') print('主进程结束') print(f'查看主主进程{os.getpid()}')#同样常看进程id f = open('yy.txt')
3.守护进程
当主进程结束时,子进程也会被回收
from multiprocessing import Processimport timedef demo(name): print(f'start.....{name}') time.sleep(8) print(f'end....{name}') print('子进程结束啦啊啦啦啦啦啦啦')if __name__ == '__main__': p = Process(target=demo,args=('童子鸡一号', )) p.daemon = True #将子进程p设为子进程 p.start() time.sleep(9)#如果主进程运行时间比子进程块则主进程被回收时子进程也会被回收不会再执行 print('这个王爷有点帅')
4.进程之间数据是隔离的
from multiprocessing import Processimport timenumber = 10def func(): global number number = 100 print(number)#100# def func2(number):# number += 100 # print(number)if __name__ == '__main__': p = Process(target=func) # p1 = Process(target=func2, args=(number,)) p.start() # p1.start() p.join() # p1.join() time.sleep(1) print(number)#10 print(number)#10
5.互斥锁:
抢票栗子:from multiprocessing import Processfrom multiprocessing import Lock #进程互斥锁import randomimport timeimport json#查看余票def search(name): #读取json文件中的数据 with open('data.json','r',encoding='utf-8') as f: data_dic = json.load(f) print(f'用户{name}查看余票,余票还剩{data_dic.get("number")}')#购买火车票如果购买成功就减少票数def buy(name): with open('data.json','r',encoding='utf-8')as f: data_dic = json.load(f) #到这一步谁先谁得到票 if data_dic.get('number') > 0: data_dic['number'] -= 1 #模拟网络延迟 time.sleep(random.randint(1,3)) with open('data.json','w',encoding='utf-8') as f: json.dump(data_dic,f) print(f'用户{name},抢票成功') else: print(f'用户{name},抢票失败')def run(name,lock): #假设多人购买票转成串行一个一个买 search(name) lock.acquire() #加锁 buy(name) lock.release() #释放锁if __name__ == '__main__': lock = Lock() #开启并发多进程,实习呢并发 for line in range(7): obj = Process(target=run,args=(f'史迪仔{line}',lock)) obj.start()
6.队列
相当于第三方管道。
from multiprocessing import Queue #multiprocessing提供的队列,先进先出from multiprocessing import JoinableQueue # 基于 Queue 封装的队列 先进先出import queue # python内置的队列 先进先出 #队列中没有了put_nowait会报错q_obj = Queue(5) #表示队列中只能存在五份数据q_obj.put_nowait('json')print('田间草木深1')q_obj.put_nowait('1')print('田间草木深2')q_obj.put_nowait('2')print('田间草木深3')q_obj.put_nowait('3')print('田间草木深4')q_obj.put_nowait('4')print('田间草木深5')q_obj.put_nowait('5')print('田间草木深6')from multiprocessing import Queue #multiprocessing提供的队列,先进先出 #队列中没有了put不会报错进入阻塞状态q_obj = Queue(6)q_obj.put('json')print('田间草木深1')q_obj.put('1')print('田间草木深2')q_obj.put('2')print('田间草木深3')q_obj.put('3')print('田间草木深4')q_obj.put('4')print('田间草木深5')q_obj.put('5')print('田间草木深6')
7.IPC机制(进程之间通信)
from multiprocessing import Processfrom multiprocessing import JoinableQueueimport timedef stak(q): x = 100 q.put(x) #将数据添加到对列中 print('添加进程') time.sleep(3) print(q.get()) #取出队列中的数据现在是1234def task2(q): res = q.get() #取出队列中的数据现在是x的值100 print(f'获取的数据时是{res}') q.put(1234) #将1234添加到数据队列q中if __name__ == '__main__': q = JoinableQueue(5) #创建一个存放五份数据的队列 p1 = Process(target=stak,args=(q,)) p2 = Process(target=task2,args=(q,)) p1.start() p2.start() 总而言之言而总之就是队列中的数据可以被进程共享
8.生产者与消费者
生产者:生产数据的
消费者:使用数据的
from multiprocessing import JoinableQueuefrom multiprocessing import Processimport timedef producer(name, food, q): msg = f'{name}生产了{food}' q.put(food) print(msg)def customer(name, q): while True: try: time.sleep(1) food = q.get_nowait() msg = f'{name}吃了{food}' print(msg) except Exception: breakif __name__ == '__main__': q = JoinableQueue() #C=创建两个生产者 for line in range(5): p = Process(target=producer, args=('tank', f'猪饲料{line}',q)) p.start() #创建两个消费者 c1 = Process(target=customer,args=('jason',q)) c2 = Process(target=customer,args=('sean',q)) c1.start() c2.start()
9.线程
进程:资源单位
线程:执行单位
线程与进程都是虚拟的概念,为了跟好的表达某种事物
开启一个进程一定自带一个线程,线程才是真正的执行者。
为什么使用线程:
节省资源的占用
开启进程:1)产生一个内存空间,申请一块资源。
2)自动产生一个主进程。
3)开启子进程的速度要比子线程慢很多。
开启线程: 1)一个进程里可以开启多个线程,从进程的内存空间中申请执行单位。
2)节省资源
IO密集型:多线程
io时间由用户定:阻塞:切换+保存状态
计算密集型:多进程
计算时间由操作系统定:计算时间很长:切换+保存状态
进程与进程之间数据是隔离的,线程与线程数据之间是共享的
from threading import Threadimport timenumber = 1000# #启动线程方式一# def task():# global number# number = 100# print('start.....')# time.sleep(1)# print('end....')## if __name__ == '__main__':# t = Thread(target=task# t.start()# print('主进程')# print(number)#启动线程方式二class Mythread(Thread): def run(self): print('start...') time.sleep(1) print('end...')if __name__ == '__main__': t = Mythread() t.daemon = True t.start() print('主进程') #查看子进程class Mythread(Thread): def run(self): print(f'start...{current_thread().name}') time.sleep(1) print(f'end...{current_thread().name}')if __name__ == '__main__': t = Mythread() t.daemon = True t.start() t.join() print('主进程') print(number)
10.线程锁与进程锁一样
from threading import Lockfrom threading import Threadimport timelock = Lock()# 开启10个线程,对一个数据进行修改number = 100def task(): global number lock.acquire()#加锁时修改数据按顺序变成串联一个一个修改 number2 = number time.sleep(1) number = number2 - 1 lock.release() #解锁if __name__ == '__main__': list1 = [] for line in range(10): t = Thread(target=task) t.start() list1.append(t) # for t in list1: t.join() print(number) # 90 print('主进程')
来源:https://www.cnblogs.com/cyfdtz/p/12018623.html