• 进程1


    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.开启进程的两种方式(***)

      本质:在内存中申请一块独立的内存空间

      windows下创建进程内部实现:

        以模块导入的方式将代码拷贝到新申请的内存空间中

    创建进程的开销比较大:
      申请内存空间
      拷贝代码

      创建进程的方式 1:

        自己定义一个函数,调用Process(target='自己写的函数',args=(v1,))

    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

        写一个类继承Process,在里面固定写一个run方法

    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
    
    
    
    # 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.进程对象其他相关方法

    查看进程id号
      current_process().pid    >>> current_process()返回的是Process()
      os.getpid()  os.getppid()
      
      terminate()  主动发起杀死进程的操作
      time.sleep(0.1)
      is_alive()  判断进程是否存活

    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('')
    
    
    
    >>>:
        False
        主

     6.僵尸进程与孤儿进程  

      子进程结束之后不会立即释放pid等资源信息

      任何进程都会步入僵尸进程,当主进程不停的创建子进程的时候,会有害

    两种情况下会回收子进程的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
  • 相关阅读:
    在oracle配置mysql数据库的dblink
    项目中非常有用并且常见的ES6语法
    原生js的容易忽略的相似点(二)
    原生js的容易忽略的相似点(一)
    json常用方法和本地存储方法
    vue-cli下面的config/index.js注解 webpack.base.conf.js注解
    vue跨域解决及打包
    js里面Object的一些方法
    vw+vh+rem响应式布局
    toast插件的简单封装(样式适用pc后台管理系统的场景)
  • 原文地址:https://www.cnblogs.com/zhouyongv5/p/10820946.html
Copyright © 2020-2023  润新知