上节课复习:
1.僵尸进程与孤儿进程
kill-CHLD查看父进程是否有僵尸进程 kill-9杀掉父进程
今日内容:
一:IPC机制(进程之间的通信)
真正进程之间的通信会用共享内存:
1.管道
tasklist | findstr xxx
ps aux | grep xxx
2.队列 是管道+锁实现的
from multiprocessing import Queue q=Queue(3) #只能放3个值 q.put([1,2,3]) #放值 q.put([4,5]) q.put([11,22,33]) print(q.get()) #取值
print(q.get())
print(q.get())
print(q.get(block=False)) #一旦队列的值被取完之后,立马就抛出异常
结果是: raise Empty _queue.Empty
只能在一台机上多个本地进程的使用,不适用于网络联机
二:生产者消费者模型******
p.jion的作用和用法
在主进程运行过程中如果想并发地执行其他的任务,我们可以开启子进程,此时主进程的任务与子进程的任务分两种情况
情况一:在主进程的任务与子进程的任务彼此独立的情况下,主进程的任务先执行完毕后,主进程还需要等待子进程执行完毕,然后统一回收资源。
情况二:如果主进程的任务在执行到某一个阶段时,需要等待子进程执行完毕后才能继续执行,就需要有一种机制能够让主进程检测子进程是否运行完毕,在子进程执行完毕后才继续执行,否则一直在原地阻塞,这就是join方法的作用
from multiprocessing import Process
import time
import random
import os
def task():
print('%s is piaoing' %os.getpid())
time.sleep(random.randrange(1,3))
print('%s is piao end' %os.getpid())
if __name__ == '__main__':
p=Process(target=task)
p.start()
p.join() #等待p停止,才执行下一行代码
print('主')
该模型有两种角色,生产者和消费者;生产者负责产生数据,消费者负责取走数据;
生产者与消费者通过队列联系,优点是:解耦合,平衡了生产者的生产力与消费者的处理能力
from multiprocessing import Process,Queue import time,random def producer(q,name,food): for i in range(3): res='%s%s' %(food,i) time.sleep(random.randint(1,3)) q.put(res) print('%s生产了 %s' %(name,res)) def consumer(q,name): while True: res=q.get() if res is None: #配合下方的 q.get(None) 来解除在吃货把厨师的东西都吃完后进行原地死等 break time.sleep(random.randint(1,3)) print('%s 吃了 %s' %(name,res)) if __name__ == '__main__': q=Queue() p1=Process(target=producer,args=(q,'厨师1','包子')) p2=Process(target=producer,args=(q,'厨师2','烧麦')) p3=Process(target=producer,args=(q,'厨师3','馒头')) c1=Process(target=consumer,args=(q,'lxx')) c2=Process(target=consumer,args=(q,'hxx')) p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() q.put(None) q.put(None) print('主') 结果是: 厨师1生产了 包子0 厨师2生产了 烧麦0 厨师3生产了 馒头0 lxx 吃了 包子0 lxx 吃了 馒头0 hxx 吃了 烧麦0 厨师3生产了 馒头1 厨师1生产了 包子1 厨师2生产了 烧麦1 厨师1生产了 包子2 厨师2生产了 烧麦2 厨师3生产了 馒头2 主 hxx 吃了 包子1 lxx 吃了 馒头1 lxx 吃了 包子2 hxx 吃了 烧麦1 lxx 吃了 烧麦2 hxx 吃了 馒头2
三:线程理论******
1.定义
一条流水线式的过程,具体指的是进程内代码运行的过程
线程是一个执行单位,CPU执行的就是线程
(1)同一进程下的不同线程共享该进程的内存资源
(2)开启子线程的资源开销远远小于子进程
四:开启线程的2种方式******
方式1
from threading import Thread import os def task(name): print('%s is running' %name) if __name__ == '__main__': t=Thread(target=task,args=('线程1',)) t.start() print('主线程',os.getpid()) 结果是: 线程1 is running 主线程 5628
验证主线程和子线程之间的隔离性
from threading import Thread,current_thread import os n=100 def task(): n=0 if __name__ == '__main__': t=Thread(target=task) t.start() t.join() print('主线程',n) 结果是:主线程 100
方法2:
from threading import Thread class Mythread(Thread): def __init__(self,name): super().__init__() self.name=name def run(self) -> None: print('%s is running' %self.name) if __name__ == '__main__': t=Mythread('线程1') t.start() 结果是: 线程1 is running
五:守护线程
守护线程守护的是主线程的生命周期
六:互斥锁
from threading import Thread,Lock
import os,time
n=100
mutex=Lock() #互斥锁
def task():
global n
with mutex: #互斥锁
temp=n
time.sleep(0.1)
n=temp-1
print(n)
if __name__ == '__main__':
mythread=[]
for i in range(100):
t=Thread(target=task)
mythread.append(t)
t.start()
for obj in mythread:
obj.join()
print('主',n) #结果是: 主,