进程基础
进程
1.程序与进程的区别
程序:一堆代码
进程:一堆代码的运行过程
2.进程调度
当代操作系统调度:
时间片轮转法+分级反馈队列
-
先来先服务调度
a,b程序,若a程序先来,先占用CPU。
缺点:程序a先使用,程序b必须等待程序a使用CPU结束后才能使用。
-
短作业优先调度:
a,b程序,谁的用时短,先优先调度使用CPU。
缺点:若程序a使用时间长,有N个程序使用时间短,必须等待所有用时短的程序结束后才能使用。
-
时间片轮转法
CPU执行的时间1秒中,加载N个程序,要将1秒等分成多个N个时间片。
-
分级反馈队列
将执行优先分为多层级别。
- 1级:优先级最高
- 2级:优先级第二
- 3级:优先级第三。。。以此类推
3.进程的三个状态
-
就绪态:
所有进程创建时都会进入就绪态,准备调度。
-
运行态:
调度后的进程,进入运行态
-
阻塞态:
凡是遇到IO操作的进程,都会进入阻塞态。
若IO结束,必须重新进入就绪态。
4.同步和异步
指的是提交任务的方式
4.1 同步
若有两个任务需要提交,在提交第一个任务时,必须等待该任务执行结束后,才能继续提交并执行第二个任务。
4.2 异步
若有两个任务需要提交,在提交第一个任务时,不需原地等待,立即可以提交并执行第二个任务。
5.阻塞与非阻塞
5.1 阻塞
阻塞态。遇到IO一定会阻塞。
5.2 非阻塞
非阻塞态。即就绪态和运行态
6.进程号回收的两种方式
- join方法(from multiprocessing import Process),可以回收子进程与主进程。
- 主进程正常结束,子进程与主进程也会被回收。
7.创建进程的两种方法
方法一:
导入Process
类,直接实例化创建进程。
from multiprocessing import Process
import time
def task(name):
print(f"{name}函数开始执行。。。")
time.sleep(0.5)
print(f'{name}函数执行结束。')
if __name__ == '__main__':
p = Process(target=task,args=('task',)) # args要传元组
p.start()
print('主进程结束')
方法二:
导入Process
类,继承此类创建新类。
类内部需要创建run
方法,该方法则为进程需要完成的任务函数。
实例化新类,通过新类对象.start()
开启进程。
from multiprocessing import Process
import time
class SomeProcess(Process):
def run(self):
print(f"{self.name}函数开始执行。。。")
time.sleep(0.5)
print(f'{self.name}函数执行结束。')
if __name__ == '__main__':
p = SomeProcess()
p.start()
# p.join()
print('主进程结束')
8.僵尸进程与孤儿进程(了解)
8.1 僵尸进程
指的是子进程已经结束了,但PID号还在,未销毁。
缺点:占用PID号,占用操作系统资源。
8.2 孤儿进程
指的是子进程还在执行,但父进程意外结束了。
操作系统优化机制:提供一个福利院,帮你回收没有父进程的子进程。
9.守护进程
指的是主进程结束后,该主进程产生的所有子进程跟着结束,并回收。
10.进程互斥锁
加锁可以保证
让并发变成串行,牺牲了执行效率(速度),保证了数据安全。
在程序并发执行时,需要修改数据时使用。
缺点:
- 效率低
- 需要自己加锁处理
11.队列
1.什么是队列
队列一种用来储存数据的容器,它的特性是:先进先出。可以用来实现多进程之间的数据传递。
相当于内存中产生一个队列空间,可以存放多个数据,但是数据的顺序是由先进去的排在前面。
优点:
- 效率高
- 帮我们处理好锁的问题
2.如何使用队列
from multiprocessing import Queue
# 调用Queue类,实例化出一个对象q
q = Queue(5) # 5代表可以存放5个数据,如果没写,则可以存放无限大的数据
# 把数字1添加到队列当中
q.put(1)
# 添加数据,如果队列满了,就会报错
q.put_nowait(2)
# 判断队列中是否已满
print(q.full())
# 取出队列中的数据,若队列中没有数据,则会进入IO等待
print(q.get())
# 取出数据,若队列中没有则会报错
print(q.get_nowait())
# 判断队列是否为空
print(q.empty())
'''
False
1
2
True
'''
12.IPC(进程间通信)
进程间数据是相互隔离的,若想实现进程间通信,可以利用队列。
from multiprocessing import Process
from multiprocessing import Queue
def test1(q):
data = '数据hello'
q.put(data)
print('进程1开始添加数据到队列中..')
def test2(q):
data = q.get()
print(f'进程2从队列中获取数据{data}')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=test1, args=(q, ))
p2 = Process(target=test2, args=(q, ))
p1.start()
p2.start()
print('主')
'''
主
进程1开始添加数据到队列中..
进程2从队列中获取数据数据hello
'''