进程、线程
进程、线程是操作系统中的概念
进程是操作系统的一个独立单位,进程、线程都是操作系统中的基本概念,也就是说进程和线程都是操作系统层面的东西,进程和线程都是操作系统来调度的,不是程序员自己操控的。(与后续所学的协程做对比,协程不是操作系统的概念,是程序员层面的,由程序员自己调用,不是操作系统调用的,操作系统中没有这个概念)
进程
进程的用处:用来做任务的,听歌、看视频等。
进程简单来说就是一个过程,而线程是真正干活的。
进程和线程的区别
1、程序是死的东西,无任何生命意义。
2、进程是有生命周期的,当一个程序结束,进程就不存在了。
进程中要有线程,进程中如果没有线程是无意义的,一个进程中可以有多个线程,一个进程中至少有一个线程。
CPU工作机制(来回切换做到的)
当cpu遇到I/O系统的时候,会剥夺CPU的执行权限
当遇到的任务需要占用大量时间时,也会剥夺执行权限
I/O密集型:
遇到阻塞,不会占用大量CPU资源,需要等待
计算密集型:
没有遇到阻塞,但是需要占用大量CPU资源,也不需要等待
操作系统的调度算法
1、先来先服务调度算法
2、短作业优先调度算法
3、时间片轮转法(按时间)
4、多级反馈队列(以上三种不适用就用这种)
操作系统会自行选择哪一种算法。
进程的并发和并发
并行:同一时刻,同时执行。
想要同一时刻同时执行,要cpu有多个处理器(核)
单核的cpu无法并行
并发:在一段时间内,看起来是同时执行任务,不是同一时刻。
同步异步阻塞非阻塞
同步异步
关注的是消息通信机制。
同步:调用者主动等待调用结果
异步:调用发出后,不会立即得到结果,而是调用发出发出后,被调用者通过状态通知来告诉调用者。
举个例子:
例如买书,
如果是同步通讯机制:问书店老板是否有这本书,老板说查一下,稍等会,然后购买者就等,等到老板返回结果。
如果是异步通讯机制:问老板是否有这本书,老板说找到后给购买者打电话。但是其他人在此时也可以询问老板是否有书。
更多关注老板
阻塞非阻塞
关注的是程序在等待调用结果时的状态。
堵塞:调用结果返回之前,线程会被挂起,直到得到结果,才会返回。
非堵塞:不立刻得到结果之前,该调用不会阻塞当前线程。
例如:阻塞时调用:在书店老板找到这本书之前,会一直挂起,直到找到这本书。
非阻塞调用:在问书店老板是否有在这本书,不管有没有,都会去一边,偶尔返回看老板是否有给结果。(这个期间别人用不了这个窗口)
更多关注自己
同步阻塞,同步非阻塞,异步阻塞,异步非阻塞


开启进程
使用的模块:multiprocess
在windows系统,开启进程必须写在__main__中,其他系统不用加。
from multiprocessing import Process def task(): with open('a.txt','w',encoding='utf8') as f: f.write('helloworld') if __name__ == '__main__': p = Process(target=task) #还没开始,只是实例化一个对象 p.start() #调用这个方法开始进程
group=None, target=None, name=None, args=(), kwargs={},*, daemon=None
每一个进程都有:进程名,进程id等属性
name: 代表的是进程的名字
args=(), 传参数的
kwargs={},
daemon:守护进程
关于子进程和主进程:他们并不是包含关系,只是主进程带动了子进程而已,而在下列例子中task是子进程,调用task是主进程,而py文件又是前一个的主进程,当py文件是子进程的时候,pycharm是主进程。
简单的举例 :
from multiprocessing import Process def task(name,age): print('hi') print('name:',name) print('age:',age) if __name__ == '__main__': # group=None, target=None, name=None, args=(), kwargs={},*, daemon=None p = Process(target=task,name='lin',args=('rui',),kwargs={'age':18}) p.start() #查看进程名字 print(p.name) ''' lin #先走主进程,因为子进程开启需要时间,所以在主进程走完才会走子进程 hi name: rui age: 18 '''
加入daemon(守护进程)
from multiprocessing import Process def task(name,age): print('hi') print('name:',name) print('age:',age) if __name__ == '__main__': # group=None, target=None, name=None, args=(), kwargs={},*, daemon=None p = Process(target=task,name='lin',args=('rui',),kwargs={'age':18}) p.daemon = True ##守护进程的作用:主进程结束,子进程也结束,并且守护进程放在start之前,默认是False p.start() #查看进程名字 print(p.name)
方法介绍
join 等待子进程结束,再执行主进程
from multiprocessing import Process def task(name,age): print('hi') print('name:',name) print('age:',age) if __name__ == '__main__': # group=None, target=None, name=None, args=(), kwargs={},*, daemon=None p = Process(target=task,name='lin',args=('rui',),kwargs={'age':18}) # p.daemon = True #守护进程的作用:主进程结束,子进程也结束,并且守护进程放在start之前 p.start() p.join() #先执行子进程再执行主进程 #查看进程名字 print(p.name) ''' 结果: 因为加了join所以先执行子进程,子进程走完才走主进程 hi name: rui age: 18 lin '''
from multiprocessing import Process def task(name,age): print('hi') print('name:',name) print('age:',age) if __name__ == '__main__': # group=None, target=None, name=None, args=(), kwargs={},*, daemon=None p = Process(target=task,name='lin',args=('rui',),kwargs={'age':18}) p.start() p.terminate() #杀死进程 import time #查看进程名字 time.sleep(1) print(p.is_alive()) #判断进程是否存在 print(p.name) #杀死的只是task这个子进程,主进程还存活,可以运行 ''' 结果: False lin '''
join 执行完子进程,子进程完毕再执行主进程
(例子在多进程循环中展示)
如何开启多进程
因为进程需要时间,所以进程开启需要时间,所以执行无顺序。
关于join:
当join放进循环,会串行执行,时间长。
# 加入循环,多次传值 from multiprocessing import Process import time def task(i): print('hi:',i) time.sleep(1) if __name__ == '__main__': start = time.time() for i in range(5): # group=None, target=None, name=None, args=(), kwargs={},*, daemon=None p = Process(target=task,args=(i,)) p.start() p.join() print('hihihi') print('time:',time.time()-start) ''' 结果: hi: 0 hi: 1 hi: 2 hi: 3 hi: 4 hihihi time: 5.777955770492554 虽然有了顺序,但是时间会变得很慢,进程就无意义 '''
当join存放在子进程分别执行完,就会并行执行,时间短。
# 加入循环,多次传值 from multiprocessing import Process import time def task(i): print('hi:',i) time.sleep(1) if __name__ == '__main__': l = [] start_time = time.time() for i in range(5): p = Process(target=task,args=(i,)) p.start() l.append(p) for j in l: j.join() print('123') print(time.time() - start_time) ''' 结果: hi: 0 hi: 1 hi: 2 hi: 3 hi: 4 123 1.186903953552246 '''
进程锁
锁:为了保证数据安全。
lock.acquire() 上锁
lock.release()释放锁
为了防止调用导致的调用进程时间短,程序要按顺序并且绑在一起执行。
from multiprocessing import Process from multiprocessing import Lock def task(i,lock): lock.acquire() #上锁 print('%s进程来了'%i) print('%s进程走了'%i) lock.release() #释放锁 if __name__ == '__main__': lock = Lock() for i in range(5): p = Process(target=task,args=(i,lock)) p.start() ''' 结果: 1进程来了 1进程走了 0进程来了 0进程走了 2进程来了 2进程走了 3进程来了 3进程走了 4进程来了 4进程走了 '''
进程间的通信(IPC机制)
进程是可以开启多个的,进程和进程之间相互独立,互补影响,进程是操作系统一个独立单元。
一个进程崩溃了,其他进程不受影响。
一个进程中不能修改另一个进程的数据,言外之意是进程之间的数据是隔离的,互不影响
想要在一个进程中使用一个进程的数据,需要让进程之间通信。