并发编程预热
一、操作系统的发展史
1)第一代计算机:真空管和穿孔卡片
- 优点:程序员在申请的时间段内独享整个资源,可以即时地调试自己的程序
- 浪费计算机资源,一个时间段内只有一个人用。
2)第二代计算机:晶体管和批处理系统
-
优点:批处理,节省了机时和资源
-
缺点:
整个流程需要人参与控制,将磁带搬来搬去*
计算的过程仍然是顺序计算-》串行
程序员原来独享一段时间的计算机,现在必须被统一规划到一批作业中,等待结果和重新调试的过程都需要等同批次的其他程序都运作完才可以(这极大的影响了程序的开发效率,无法及时调试程序)
3)第三代计算机:集成电路复用和多道程序设计
-
多道技术
空间上的复用:共用一个内存条,每一个进程都是自己独立的内存空间,互不干扰,物理级别的隔离
时间上的复用:共用一个CPU,IO的时候占用时间过长!
二、创建并开启子进程的两种方式
2.1方式一
#单个进程
from multiprocessing import Process
import time
def Text():
print('我是一个子进程')
print('我的进程开始了')
time.sleep(2)
print('我的进程结束了')
if __name__ == '__main__': #windows下必须要写这一句,不然会报错
p = Process(target = Text) #实例化产生一个对象
p.start() # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
time.sleep(5)
print('我是主进程,我要结束了')
#多个进程
from multiprocessing import Process
import time
def Text(x):
print(f'我是子进程{x}')
print(f'{x}的进程开始了')
time.sleep(2)
print(f'{x}的进程结束了')
if __name__ == '__main__': #windows下必须要写这一句,不然会报错
p1 = Process(target = Text,args=('yjy',)) #实例化产生一个对象 子进程1
p2 = Process(target = Text,args=('ypp',)) #实例化产生一个对象 子进程2
p1.start() # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
p2.start() # 告诉操作系统我要开子进程,告诉完了这行代码就算执行完了,接着往下走,具体操作系统什么时候开子,开多长时间跟你没关系
time.sleep(5)
print('我是主进程,我要结束了')
2.2 方式二
from multiprocessing import Process
import time
class Text(Process): #定义一个类,让他继承Process
def __init__(self,name): #重写__init__
super().__init__() #继承父类的__init__方法
self.name = name
def run(self): #定义一个函数
print(f'子进程的姓名为{self.name},子进程开始')
time.sleep(2)
print(f'{self.name}进程结束')
if __name__ == '__main__':
p = Text('yjy')
p.start() #通知操作系统子进程开始
print('主进程结束')
三、验证进程的内存空间隔离
from multiprocessing import Process
import time
x = 0 #定义一个变量x
def Check():
global x
x = 100
print(f'子进程的x:{x}')
if __name__ == '__main__':
p = Process(target=Check)
p.start()
print(f'父进程的x:{x}')
-----------------------------------------------------------------------------------
父进程的x:0
子进程的x:100
父进程的x和子进程的x不是一个值,说明他们两个进程互不影响!
四、僵尸进程与孤儿进程
僵尸进程(有害):当子进程结束的时候,不会将所有内容都释放掉,他会留下自己的pid(类似身份证号码)供父进程来查看,此所谓进程死了没死干净,这就是僵尸进程,他会等待父进程最后把他处理掉
孤儿进程(无害):一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。