进程的概念
什么是进程?
正在进行的一个过程或者说是一个任务,而负责执行任务的是CPU
举例(单核+多道,实现多个进程的并发执行)
"""
Eg:
我在同一个时间段内有多个任务,比如做饭、学习、打游戏、刷视频
但是同一个时间我只能做一件事(CPU同一时间只能干一个活),如何完成多任务并发执行的效果?
我做一会饭,再去学一会习,再打一会游戏。。。等等,这就保证每个任务都在进行中了
"""
进程和程序的区别:
1、程序仅仅是一堆代码,它没有生命周期,
2、进程则是程序运行的过程,他是有生命周期的,即程序结束进程死亡
"进程中最重要的就是线程,进程中没有线程是没有意义的,一个进程中可以有多个线程,但是一个进程中最少要有一个线程"
进程和线程都是由操作系统来调度的
进程则是操作系统的一个独立单元
举例:
我正在做一道菜,首先要有一道菜谱,其次就是做菜的原材料(白菜、蒜泥、肉末等等)
在这个例子中:
菜谱就是程序
"我"就是CPU
原材料就是输入的数据
我阅读菜谱以及做菜的过程就是进程
"""需要强调的是:同一个程序执行两次,那也是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播放苍井空,一个可以播放饭岛爱。"""
补充:CPU的工作机制
1. 当CPU遇到I/O操作的时候,会剥夺CPU的执行权限
2. 当遇到的任务需要占用大量的时间的时候,也会剥夺执行权限
"""其实CPU的工作机制是来回切换做到的"""
I/O密集型:
input output
"""遇到阻塞,但是不需要占用大量的CPU资源,需要等待,比如:sleep"""
计算密集型
"""没有遇到阻塞,但是需要占用大量的CPU资源,也不需要等待"""
并发与并行
无论是并发还是并行,在用户看来都是"同时"运行的,不管是进程还是线程,都只是一个任务而已,真干活的还是CPU,CPU来做这些任务,但是一个CPU同一时间内只会执行一个任务。
并发:
并发就是伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发,(并行也属于并发)
Eg:
你是一个cpu,你同时谈了三个女朋友,每一个都可以是一个恋爱任务,你被这三个任务共享,要玩出并发恋爱的效果,应该是你先跟女友1去看电影,看了一会说:不好,我要拉肚子,然后跑去跟第二个女友吃饭,吃了一会说:那啥,我去趟洗手间,然后跑去跟女友3开了个房
并行:"在同一时刻",同时执行多个任务,前提是多核CPU
有四个核,六个任务,这样同一时间有四个任务被执行,假设分别被分配给了cpu1,cpu2,cpu3,cpu4, 一旦任务1遇到I/O就被迫中断执行,此时任务5就拿到cpu1的时间片去执行,这就是单核下的多道技术,而一旦任务1的I/O结束了,操作系统会重新调用它(需知进程的调度、分配给哪个cpu运行,由操作系统说了算),可能被分配给四个cpu中的任意一个去执行
同步异步阻塞非阻塞
"""描述的是任务的提交方式"""
同步:
任务提交以后,原地等待任务的返回结果,等待的过程中不做任何事(干等)
"程序层面上表现的感觉就是卡住了"
异步:
任务提交之后,不原地等待任务的返回结果,直接去做其他的事
那么提交的任务结果如何获取?
任务的返回结果会有一个异步回调机制自动处理
"描述的是程序运行状态"
阻塞:阻塞态
非阻塞:就绪态、运行态
理想状态:我们应该让我们的写的代码永远处于就绪态和运行态之间切换
"上述概念的组合:最高效的一种组合就是异步非阻塞"
开启进程的两种方式
第一种:
from multiprocessing import Process
import time
def index(name):
print(f"这是{name}")
time.sleep(3)
print("from index")
# 开启进程必须要使用__main__要不然会报错
if __name__ == '__main__':
"""
参数:
group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None
每一个进程都有:进程名,进程id等属性
name: 代表的是进程的名字
args=(), 传参数的
kwargs={},
daemon:守护进程
"""
# 实例化一个类得到一个对象
p = Process(target=index, args=('kevin',))
# 容器类型哪怕里面只有一个元素,建议也要使用逗号隔开
# 2、开启进程
p.start() # 告诉系统帮助你开启一个进程 异步
"""
执行结果:
这是kevin
from index
"""
第二种:
from multiprocessing import Process
import time
class MyProcess(Process):
def run(self, ):
print("from run")
time.sleep(3)
print("from index")
if __name__ == '__main__':
p = MyProcess()
p.start()
"""
执行结果:
from run
from index
"""
守护进程
from multiprocessing import Process
import time
def index(name):
print(f"这是{name}")
time.sleep(3)
print("from index")
# 开启进程必须要使用__main__要不然会报错
if __name__ == '__main__':
# 实例化一个类得到一个对象
p = Process(target=index, args=('kevin',))
# 容器类型哪怕里面只有一个元素,建议也要使用逗号隔开
# 开启守护进程
p.daemon = True
# 2、开启进程
p.start() # 告诉系统帮助你开启一个进程 异步
print("先执行了这里")
"""
没有开启守护进程的执行结果:
先执行了这里
这是kevin
from index
现在的现象是:主进程代码先执行,然后执行子进程里的代码,并且主进程代码执行完毕之后,子进程的代码并没有结束
开启守护进程之后的结果:
先执行了这里
"""
守护进程的作用是什么呢 :
作用是主进程结束了,子进程也会立马结束不再执行
方法介绍
# p.terminate() # 杀死进程
# # True
# import time
# time.sleep(1)
#
# # False
# print(p.is_alive()) # 查看p进程是否存活
# join
# 现在让你先执行子进程中的代码,在执行主进程中的代码?
p.join() # 先等待子进程执行完毕,在执行主进程
总结
"""
创建进程就是在内存中申请一块内存空间将需要运行的代码丢进去
一个进程对应在内存中就是一块独立的内存空间
多个进程对应在内存中就是多块独立的内存空间
进程与进程之间数据默认情况下是无法直接交互,如果想交互可以借助于第三方工具、模块
"""
join方法
join方法是让主进程等待子进程代码运行结束以后,再继续执行,不影响其他子进程的执行
from multiprocessing import Process
import time
def index(name):
print(f'name:{name}')
time.sleep(3)
print("from index")
if __name__ == '__main__':
p = Process(target=index, args=("kevin",))
p1 = Process(target=index, args=("tom",))
p2 = Process(target=index, args=("tank",))
p.start()
p.join()
p1.start()
p1.join()
p2.start()
"""
执行结果:
name:kevin
from index
name:tom
from index
name:tank
from index
也就是说join方法会在一个对象执行完所有子进程以后再去执行主进程
"""
开启多进程
from multiprocessing import Process
import time
def index(i):
print(f"index:{i}")
time.sleep(1)
if __name__ == '__main__':
satrt = time.time()
p_list = []
# 开启多进程以后他就是无序的
for i in range(5):
p = Process(target=index, args=(i,))
# 开启进程
p.start()
# 将得到的进程放到定义好的列表中
p_list.append(p)
# 遍历列表,拿出来每一个子进程
for j in p_list:
j.join()
end = time.time()
print(f"time:{end - satrt}") # time:1.1487295627593994
"""
初次执行结果:
index:0
index:1
index:3
index:2
index:4
"""
"""
多进程:
index:0
index:1
index:3
index:2
index:4
"""
进程锁
锁:是为了保证数据的安全
from multiprocessing import Process
from multiprocessing import Lock
def index(i, lock):
# 上锁
lock.acquire()
print(f"from {i}个进程进来了")
print(f"from {i}个进程出去了了")
# 解锁
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(5):
p = Process(target=index, args=(i, lock))
p.start()
p.join()
"""
执行结果:
from 0个进程进来了
from 0个进程出去了了
from 1个进程进来了
from 1个进程出去了了
from 2个进程进来了
from 2个进程出去了了
from 3个进程进来了
from 3个进程出去了了
from 4个进程进来了
from 4个进程出去了了
"""
进程之间的相互隔离
# 进程是可以开启多个的,进程与进程之间是相互独立的,互补影响,进程是操作系统的一个独立单元
一个进程崩溃了,其他的进程不收影响
"""在一个进程中不能修改另外一个进程的数据,言外之意是进程之间的数据是隔离的,互补影响"""
from multiprocessing import Process
money = 100
def task():
global money # 局部修改全局
money = 666
print('子',money)
if __name__ == '__main__':
p = Process(target=task)
p.start()
p.join()
print(money) # 100
利用多进程实现TCP协议下的高并发程序
#############################服务端#################################
from multiprocessing import Process
import socket
def task(socker):
try:
while True:
# 接收客户端发来的消息
f_date = socker.recv(1024)
# 判断接收到的数据是否为空
if len(f_date) == 0:
continue
# 打印客户端的消息
print(f"这是客户端发来的消息{f_date.decode('utf8')}")
# 给客户端一个回馈信息
socker.send(f_date)
# 关闭服务
socker.close()
except Exception as e:
print(e)
if __name__ == '__main__':
while True:
# 1、实例得到一个对象
sever = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2、绑定一个地址
sever.bind(("127.0.0.1", 8001))
# 3、监听客户的个数
sever.listen(4)
# 4、等待客户端消息
socker, addr = sever.accept()
# 5、创建一个多项成
f = Process(target=task, args=(socker,))
# 6、开启多线程
f.start()
#############################客户端#################################
import socket
# 得到一个实例化对象
client = socket.socket()
# 绑定服务端IP
client.connect(("127.0.0.1", 8001))
# 让用户可以一直给服务端发消息
while True:
# 让用户自己输入想要发送的信息
cmd = input("请输入你要发送的信息>>>>>").strip()
# 判断发送的内容是否为空
if len(cmd) == 0:
continue
# 将信息打包发送给服务端
client.send(cmd.encode("utf8"))
# 接收到服务端回馈的信息
k_date = client.recv(1024)
# 打印服务短的消息
print(f"这是服务端发来的消息{k_date.decode('utf8')}")
# 结束服务
client.close()
"""可以有多个客户端与服务端建立连接 """