1.进程
正在进行的一个过程或者说一个任务。而负责执行任务则是cpu。操作系统核心概念 进程之间的调度操作系统来控制
并发实现的核心:切走了上次的要保留
2.进程和程序的区别
程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。
3.并发与并行
无论是并行还是并发,在用户看来都是'同时'运行的,
不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,
cpu来做这些任务,而一个cpu同一时刻只能执行一个任务
并行:同时运行,只有具备多个cpu才能实现并行
4.同步与异步
同步执行:一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行
异步执行:一个进程在执行某个任务时,另外一个进程无需等待其执行完毕,就可以继续执行,
当有消息返回时,系统会通知后者进行处理,这样可以提高执行效率
首先我要写一段代码,开启进程实现套接字服务端并发连接
1.建立连接
2.端口重用
3.绑定端口号
4.监听
5.建立连接循环
6.开启进程
7.建立通讯循环
服务端
from socket import *
from multiprocessing import Process
s=socket(AF_INET,SOCK_STREAM)
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('127.0.0.1',8081))
s.listen(5)
def talk(conn,addr):
while True:
try:
data=conn.recv(1024)
if not data:break
conn.send(data.upper())
except Exception:
break
conn.close()
if __name__=='__main__':
while True:
conn,addr=s.accept()
p=Process(target=talk,args=(conn,addr))
p.start()
s.close()
客户端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8081))
while True:
msg=input('>>>:').strip()
if not msg:continue
c.send(msg.encode('utf-8'))
data=c.recv(1024)
print(data.decode('utf-8'))
c.close()
5.守护进程
守护进程会在主进程代码执行结束后就终止
守护进程内无法再开启子进程,否则抛出异常
Process对的属性
需要掌握的第一个属性: daemon
from multiprocessing import Process
import os
import time
def work():
print('%s is working'%os.getppid()) #得到他的父进程
time.sleep(3)
if __name__ == '__main__':
p1=Process(target=work)
p2=Process(target=work)
p3=Process(target=work)
p1.daemon=True
p2.daemon=True
p3.daemon=True
p1.start()
p2.start()
p3.start()
# time.sleep(5)
print('主进程')
需要掌握的第二个属性 join
from multiprocessing import Process
import time
import os
def task():
print('%s id ruaning'%os.getppid())
time.sleep(3)
if __name__ == '__main__':
p1=Process(target=task)
p2=Process(target=task)
p3=Process(target=task)
p1.daemon=True
p2.daemon=True
p3.daemon=True
p1.start()
p2.start()
p3.start()
p1.join() #主进程等待子进程
p2.join() #最终等的就是花费时间最长的哪一个
p2.join()
print('基于初始化的结果来继续运行')
其他了解的属性 terminate alive name pid
from multiprocessing import Process
import time
import os
def task():
print('%s id ruaning'%os.getppid())
time.sleep(3)
if __name__ == '__main__':
p1=Process(target=task)
p2=Process(target=task)
p3=Process(target=task)
p1.start()
p2.start()
p3.start()
p1.terminate() #关掉p1
time.sleep(3)
print(p1.is_alive())#判断是否活着
print(p1.name) #进程名
print(p1.pid)
print('基于初始化的结果运行')
6.互斥锁
进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,
竞争带来的结果就是错乱,如何控制,就是加锁处理
互斥锁简单例子
互斥锁模拟抢票
7.队列
进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的
生产者消费者模型
8.进程的队列
1.可以往队列里放任意类型的数据,
2.先进先出
from multiprocessing import Process,Queue
q=Queue(3)
q.put('first',block=False)
q.put('second',block=False)
q.put('third',block=False)
q.put('forth',block=True,timeout=3) #e默认情况下当队列满了的时候就不能再往里面加了,锁住了所以block=True
#只会等三秒,三秒之后再不加的话就会抛异常
q.put_nowait('forth')#等同于 q.put('forth',block=True,timeout=0)#8和10行选一句
print(q.get(block=False))
print(q.get(block=False))
print(q.get(block=False))
print(q.get(block=True,timeout=3))#14和15行选择一句
print(q.get_nowait()) #等同于q.get(block=False),就是让他别再阻塞
9.进程池
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。多进程是实现并发的手段之一,需要注意的问题是:
- 很明显需要并发执行的任务通常要远大于核数
- 一个操作系统不可能无限开启进程,通常有几个核就开几个进程
- 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)
创建进程池的类:如果指定numprocess为3,则进程池会从无到有创建三个进程,然后自始至终使用这三个进程去执行所有任务,不会开启其他进程
进程池的应用
服务端
客户端
回调函数
需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:我好了额,
你可以处理我的结果了。主进程则调用一个函数去处理该结果,该函数即回调函数
我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。
回调函数
共享数据
进程池