33 进程

1.进程理论
   
 程序:一堆代码
    进程:正在运行的程序
    进程是一个实体。每一个进程都有它自己独立的内存空间,是系统进行资源分配和调度的基本单位
  
  同步和异步
*****

  针对任务的提交方式
    同步:提交任务之后原地等待任务的返回结果,期间不做任何事!
    异步:提交任务之后,不等待任务的返回结果,执行运行下一行代码!
  
阻塞与非阻塞 *****

  针对程序运行的状态
    阻塞:  遇到io操作     >>> 阻塞态(Blocked
    非阻塞:就绪或者运行态  >>> 就绪态(Ready),运行态(Running

 

先来先服务调度算法 FCFS
    #适合于CPU繁忙型作业,而不利于I/O繁忙型的作业(进程)。
短进程优先调度算法 SJ/PF
    #既可用于作业调度,也可用于进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理
时间片轮转法 RR,Round Robin
    #让每个进程在就绪队列中的等待时间与享受服务的时间成比例
    #对这些进程区别对待,给予不同的优先级和时间片,可以进一步改善系统服务质量和效率
多级反馈队列调度算法
    #(1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。
    #(2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。

    #(3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。
进程调度

2.开启进程的两种方式(***)

  创建进程的方式 1

from multiprocessing import Process
import time

def task(name): print('%s is running'%name) time.sleep(3) print('%s is over'%name) # 注意,在windows系统中,创建进程会将代码以模块的方式从头到尾加载一遍 # 一定要写在if __name__ == '__main__':代码块里面 # 强调:函数名一旦加括号,执行优先级最高,立刻执行 if __name__ == '__main__': p1 = Process(target=task,args=('Tom',)) # 这一句话只是实例化了一个Process对象 p1.start() # 告诉操作系统创建一个进程 print('主程序') >>>:   主程序   Tom is running   Tom is over

  创建进程的方式 2

from multiprocessing import Process
import time


class MyProcess(Process):

    def __init__(self, name):
        super().__init__()
        self.name = name

    # 必须写run方法
    def run(self):
        print('%s is running' % self.name)
        time.sleep(1)
        print('%s is end' % self.name)


if __name__ == '__main__':
    obj = MyProcess('Tom')
    obj.start()
    print('主程序')


>>>:
  主程序
  Tom is running
  Tom is end

 3.进程对象的join方法(***)

from multiprocessing import Process
import time


def task(name, n):
    print('%s is running' % name)
    time.sleep(n)
    print('%s is over' % name)


if __name__ == '__main__':
    start_time = time.time()
    p_list = []
    for i in range(3):
        p = Process(target=task, args=('子进程%s' % i, i))
        p.start()
        p_list.append(p)
    for i in p_list:
        i.join()
    print('主进程', time.time() - start_time)

# join的作用仅仅只是让主进程等待子进程的结束,不会影响子进程的运行

>>>:
    子进程0 is running
    子进程0 is over
    子进程1 is running
    子进程2 is running
    子进程1 is over
    子进程2 is over
    主进程 2.10233998298645


# join的作用仅仅只是让主进程等待子进程的结束,不会影响子进程的运行


# if 初始写法  ------------------------------
if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task,args=('egon',1))
    p2 = Process(target=task,args=('jason',2))
    p3 = Process(target=task,args=('kevin',3))
    start_time = time.time()
    p1.start()  # 千万要知道,这句话只是告诉操作系统需要进程
    p2.start()
    p3.start()
    # p1.join()  # 主进程等待子进程结束 才继续运行
    p3.join()
    p1.join()
    p2.join()
    print('主进程', time.time() - start_time)

 4.进程之间内存隔离(***)

# 记住 进程与进程之间数据是隔离的!!!
from multiprocessing import Process

x = 100


def task():
    global x
    x = 1
    print('task - x :', x)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print('主 - x:', x)


>>>:
    task - x : 1- x: 100

 5.进程对象其他相关方法

from multiprocessing import Process,current_process
import time
import os


def task():
    print('%s is running'%os.getpid())
    time.sleep(3)
    print('%s is over'%os.getppid())


if __name__ == '__main__':
    p1 = Process(target=task)  # 函数名(),执行优先级最高
    p1.start()
    p1.terminate()  # 杀死子进程
    time.sleep(0.1)
    print(p1.is_alive())  # 判断子进程是否存活
    print('')


# os.getppid() 可换为 current_process().pid


>>>:
    False
    主

 6.僵尸进程与孤儿进程  

  两种情况下会回收子进程的pid等信息    

    1.父进程正常结束   

    2.join方法       

  孤儿进程:父进程意外意外死亡     

     linux下:    

      init孤儿福利院;用来挥手孤儿进程所占用的资源  

      ps aux |grep 'Z'  (查看孤儿进程)

 7.守护进程

from multiprocessing import Process
import time


def task(name):
    print('%s 正活着' % name)
    time.sleep(3)
    print('%s 正常死亡' % name)


if __name__ == '__main__':
    p = Process(target=task, args=('总管',))  # 容器型:只有一个元素,加逗号","
    p.daemon = True  # 必须在p.start开启进程命令之前声明
    p.start()
    print('皇帝正在死亡')


>>>:
    皇帝正在死亡

 8.互斥锁(***) 锁千万不要随意去用 

  作用:牺牲了效率但是保证了数据的安全         

  位置:锁一定要在主进程中创建,给子进程去用   

  原因:解决多个进程操作同一份数据,造成数据不安全的情况   

  实质:加锁会将并发变成串行   

  作用点:锁通常用在对数据操作的部分,并不是对进程全程加锁

from multiprocessing import Process, Lock
import json
import time
import random


def search(i):
    with open('info', 'r', encoding='utf-8') as f:
        data = json.load(f)
    print('用户查询余票数:%s' % data.get('ticket'))


def buy(i):
    # 买票之前还得先查有没有票!
    with open('info', 'r', encoding='utf-8') as f:
        data = json.load(f)
    time.sleep(random.randint(1, 3))  # 模拟网络延迟
    if data.get('ticket') > 0:
        data['ticket'] -= 1  # 买票
        with open('info', 'w', encoding='utf-8') as f:
            json.dump(data, f)
        print('用户%s抢票成功' % i)
    else:
        print("用户%s查询余票为0" % i)


def run(i, mutex):
    search(i)
    mutex.acquire()  # 抢锁   一把锁不能同时被多个人使用,没有抢到的人,就一直等待锁释放
    buy(i)
    mutex.release()  # 释放锁


if __name__ == '__main__':
    mutex = Lock()
    for i in range(10):
        p = Process(target=run, args=(i, mutex))
        p.start()


# info 内容:
{"ticket": 1}


>>>:
    用户查询余票数:1
    用户查询余票数:1
    用户查询余票数:1
    用户0抢票成功
    用户1查询余票为0
    用户2查询余票为0

 9.进程间通信>>>IPC机制

 10.生产者消费者模型(***)

猜你喜欢

转载自www.cnblogs.com/zhouyongv5/p/10820946.html
33
今日推荐