##############################################
""" 并发编程的相关概念: 进程 1,运行中的程序,就是进程,程序是没有生命的实体,运行起来了就有生命了, 操作系统可以管理进程,进程是操作系统基本的执行单元, 2,每一个进程都有它自己的地址空间,进程之间是不会混的,比如qq不能访问微信的地址空间, 操作系统替你隔离开了,这也是操作系统引入进程这个概念的原因, ####################################### 进程的调度 1,先来先服务,有一个不好的,就是不利于短作业 2,短作业优先算法,但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。 3,时间片轮转算法,就是轮流执行,已经很科学了, 4,多级反馈队列算法,有多个队列,有一个新任务来了放入第一个队列,这是优先级加上时间片轮转,第二个任务来了放入下一级, ####################################### 并发和并行: 进程的并行:这种只有在多核cpu才可以实现, 进程的并发:这是轮流执行,由于速度很快,看起来像是一起执行的,比如一遍听音乐,一遍写代码, ###################################### 进程的三状态转换图:非常重要 1,进程一开始运行的时候,是就绪的状态,这是第一个状态,就是告诉cpu,我已经准备好可以运行了,进入排队了, 2,时间片轮转,轮到你了之后,你就运行了,这是第二个状态, 3,发生阻塞,这是第三个状态,比如你的程序让你输入内容,input方法, 这时候是阻塞的,你输入完毕了之后,就又畅通了, 这是等待I/O完成,input,sleep,文件的输入和输出, 事件处理之后,你还要进入就绪状态了, 全部处理完了,就结束了, ########################################### 同步和异步 1,同步,需要等待,需要排队,你什么也不能干, 2,异步,不需要等待,你可以去做其他事情, ########################################### 阻塞和非阻塞 1,阻塞,就是input,sleep这些,需要等待,这是阻塞, 2,非阻塞,就是跳过这些阻塞,但是程序中不可避免的需要阻塞,因为需要等待内容处理, ########################################### 同步异步和阻塞非阻塞: 同步阻塞,就是 同步非阻塞 异步阻塞 异步非阻塞,效率更高, """
##############################################
""" Python中使用多进程 运行中的程序就是一个进程。所有的进程都是通过它的父进程来创建的。 因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程。 多个进程可以实现并发效果,就会让程序的执行速度变快。 多进程有一个内置的模块,我们需要借助这个模块: from multiprocessing import Process """
##############################################
""" multiprocessing模块 在这个包中几乎包含了和进程有关的所有子模块。由于提供的子模块非常多,为了方便大家归类记忆, 我将这部分大致分为四个部分: 1,创建进程部分, 2,进程同步部分, 3,进程池部分, 4,进程之间数据共享。 multiprocessing.Process介绍 参数介绍 ############# Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调: 1. 需要使用关键字的方式来指定参数 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号 参数介绍: 1 group参数未使用,值始终为None 2 target表示调用对象,即子进程要执行的任务 3 args表示调用对象的位置参数元组,args=(1,2,'egon',) 4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18} 5 name为子进程的名称 方法介绍 ############ 1 p.start():启动进程,并调用该子进程中的p.run() 2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程, 使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁 4 p.is_alive():如果p仍然运行,返回True 5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。 timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 属性介绍 ############### 1 p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后, p不能创建自己的新进程,必须在p.start()之前设置 2 p.name:进程的名称 3 p.pid:进程的pid 4 p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可) 5 p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。 这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可) """
#################### 进程的启动方式1 ############################
创建单个进程,查看主进程id,父进程id,子进程id,
注意参数的传递,args是传递一个元组,一个元素的时候要有逗号,kargs是传递一个字典,
from multiprocessing import Process
import time
import os
def task(name):
print('{} is running!'.format(name))
print('子进程id :', os.getpid(), '父进程id :', os.getppid())
time.sleep(3)
print('{} is done!'.format(name))
# Windows开子进程要写在__name__==__main__下
# 因为开子进程会重新加载父进程的内容
if __name__ == '__main__':
print('主进程id :', os.getpid())
# 创建一个Python中的进程对象
p = Process(target=task, args=('t1', )) # 注册,这是主进程
# p = Process(target=task, kwargs={'name': 't1'})
p.start() # 调用操作系统接口启动一个进程执行命令,这是子进程,
# 现在子进程和主进程之间是异步的,如果我想在子进程结束之后再执行下面的代码,变成同步,怎么办?
p.join() # # 这个join就是在感知一个子进程的一个结束,将异步改成同步,
# print("父进程的父进程号",os.getppid()) # 这个就是pycharm的进程号,
print('--- 主进程 ----') # 加上了join,这一句会在所有的子进程结束之后才会执行
"""
没有加join:
主进程id : 8560
--- 主进程 ----
t1 is running!
子进程id : 9528 父进程id : 8560
t1 is done!
加了join:
主进程id : 8592
t1 is running!
子进程id : 6448 父进程id : 8592
t1 is done!
--- 主进程 ----
# 进程的生命周期,
# 主进程没有开启子进程,就是执行完他的代码就结束了了
# 子进程也是执行完自己的代码就结束了,
# 开启了子进程的主进程,主进程执行完了,要等待子进程结束之后,主进程才可以结束,
"""
创建多个进程:
from multiprocessing import Process
import time
def task(name):
print('{} is running!'.format(name))
time.sleep(3)
print('{} is done!'.format(name))
if __name__ == '__main__':
# 开启10个子进程
p_list = []
for i in range(10):
p = Process(target=task, args=(i, ))
p_list.append(p)
p.start()
# p.join()
[p.join() for p in p_list] # 保证前面的10个进程全部结束了,才会执行下面的代码,
print('--- 主进程 ----')
# 这种开启了多进程,可以读多个进程去存文件,取文件内容,
####################### 进程的启动方式2 #########################
# 进程的启动方式2
# 第一点,创建一个类,继承process
# 第二点,类中必须实现run方法,这个run方法里面就是子进程要执行的内容,
import os
from multiprocessing import Process
class MyProcess(Process): # 继承导入的process,
def __init__(self,name): # 为了进程能传递参数,
super().__init__() # 这是继承了父类所有的参数,
self.name=name
def run(self):
# print(os.getpid())
print("子进程号",self.pid)
print("参数",self.name) # print(os.getpid()) 这两句是一样的,
if __name__ == '__main__':
# p1=MyProcess() # 这是不传参数的
p1=MyProcess("name1") # 这是传参数的,这就是面向对象的实例化,
p2=MyProcess('name2')
p3=MyProcess('name3')
p1.start() #start会自动调用run
p2.start()
# p2.run()
p3.start()
# 三个进程之间是异步的,
p1.join()
p2.join()
p3.join()
# 三个进程都结束了才会执行下面的内容,这是把异步,变成异步,
print('主线程')
############### 进程之间是数据隔离的 ##############
# 进程之间的数据隔离问题 # 进程和进程之间的数据是否是隔离的,比如qq和微信,之间的数据是隔离的, # 几个进程之间,如果不通过特殊的手段,是不可能共享一个数据的,这个记住,没有什么可理解的, # 下面是想了一个办法,去证明这个结论,但是这个结论你记住就行了, from multiprocessing import Process def work(): global n # 声明了一个全局变量, n=0 print('子进程内: ',n) if __name__ == '__main__': n = 100 p=Process(target=work) p.start() print('主进程内: ',n)
###############################################
################################################