进程基础

进程

1.程序与进程的区别

程序:一堆代码

进程:一堆代码的运行过程

2.进程调度

当代操作系统调度:

​ 时间片轮转法+分级反馈队列

  1. 先来先服务调度

    a,b程序,若a程序先来,先占用CPU。

    缺点:程序a先使用,程序b必须等待程序a使用CPU结束后才能使用。

  2. 短作业优先调度:

    a,b程序,谁的用时短,先优先调度使用CPU。

    缺点:若程序a使用时间长,有N个程序使用时间短,必须等待所有用时短的程序结束后才能使用。

  3. 时间片轮转法

    CPU执行的时间1秒中,加载N个程序,要将1秒等分成多个N个时间片。

  4. 分级反馈队列

    将执行优先分为多层级别。

    • 1级:优先级最高
    • 2级:优先级第二
    • 3级:优先级第三。。。以此类推

3.进程的三个状态

  1. 就绪态:

    所有进程创建时都会进入就绪态,准备调度。

  2. 运行态:

    调度后的进程,进入运行态

  3. 阻塞态:

    凡是遇到IO操作的进程,都会进入阻塞态。

    若IO结束,必须重新进入就绪态。

4.同步和异步

指的是提交任务的方式

4.1 同步

若有两个任务需要提交,在提交第一个任务时,必须等待该任务执行结束后,才能继续提交并执行第二个任务。

4.2 异步

若有两个任务需要提交,在提交第一个任务时,不需原地等待,立即可以提交并执行第二个任务。

5.阻塞与非阻塞

5.1 阻塞

阻塞态。遇到IO一定会阻塞。

5.2 非阻塞

非阻塞态。即就绪态和运行态

6.进程号回收的两种方式

  1. join方法(from multiprocessing import Process),可以回收子进程与主进程。
  2. 主进程正常结束,子进程与主进程也会被回收。

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.进程互斥锁

加锁可以保证

让并发变成串行,牺牲了执行效率(速度),保证了数据安全。

在程序并发执行时,需要修改数据时使用。

缺点:

  1. 效率低
  2. 需要自己加锁处理

11.队列

1.什么是队列

队列一种用来储存数据的容器,它的特性是:先进先出。可以用来实现多进程之间的数据传递。

相当于内存中产生一个队列空间,可以存放多个数据,但是数据的顺序是由先进去的排在前面。

优点:

  1. 效率高
  2. 帮我们处理好锁的问题

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
'''    
posted @ 2019-10-21 19:40  Donner  阅读(116)  评论(0编辑  收藏  举报