• 进程


    操作系统的发展史

    老式计算机的手工操作特点:

    1.用户独占全机,不会出现因资源已被其它用户占用而等待的现象,但资源利用率低。

    2.CPU等待手工操作。CPU的利用不充分。

    手工操作属于单道程序,也就是主机内存中只能执行一个程序,其它的程序只能等待它执行完后才能执行。

    多道

    多道程序设计技术就是指允许多个程序同时进入内存并运行。

    优点:

    1.空间上的复用:

    多个程序共用一套计算机硬件

    2.时间上的复用(切换+保存状态)

    ①.当一个程序遇到IO操作,操作系统会剥夺该程序的CPU执行权限(提高了CPU的利用率,并且不影响程序的执行效率)

    ②.当一个程序长时间占用CPU操作系统也会剥夺该程序的CPU执行权限(降低程序的执行效率)

    进程理论

    进程和程序

    程序:就是一坨代码

    进程:就是正在运行的程序

    多个进程执行时的进程调度

    多个进程交替运行,操作系统必须对这些进程进行调度,这个调度也不是随机进行的,而是需要遵循一定的法则,于是有了进程的调度算法。

    1.先来先服务:谁先来就给谁先服务,先来的程序先进行运行。

    2.短作业优先调度:谁消耗的时间比较短,先运行谁。

    3.时间片轮转法和4.多级反馈队列

    同步异步、阻塞非阻塞

    同步异步:表示的是程序的运行状态

    同步:任务提交之后,原地等待的任务执行并拿到返回结果才走,期间不做任何事情(在代码层面看就是卡住了)

    异步:任务提交之后,不再原地等待,而是继续执行下一行代码(通过其它的方式拿到结果)

    阻塞和非阻塞:表示的程序的运行状态

    阻塞:阻塞态

    非阻塞:就绪态,运行态

     

    (1)就绪(Ready)状态

      当进程已分配到除了CPU外的所有资源时,只要获得处理机便可以立即执行,这是的进程状态就是就绪态。

     (2)运行(Running)状态

      当进程已获得处理机制,其它程序正在处理机上执行,这时的进程状态被称为就绪态。

    (3)阻塞(Blocked)状态

      正在执行的状态,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可能有很多种,比如等待IO才做、申请缓冲区不能满足、等待信号等。

    创建进程的两种方式

     multiprocess模块

    multiprocess并不是一个模块,而是python中一个操作、管理进程的包。之所以叫mulit是取自multiple的多功能的意思,这个包几乎包含了和进程有关的所有子模块。

    multiprocess.process模块

    Process模块

    process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建。

    #使用process模块创建进程
    from multiprocessing import Process
    import time
    
    def test(name):
        print('%s is running'%name)
        print('%s is over'%name)
    
    # windows创建进程一定要在if __name__ == '__main__':代码块内创建  否则报错
    if __name__ == '__main__':
        p = Process(target=test,args=('egon',))  #创建一个进程对象
        p.start()  # 告诉操作系统帮你创建一个进程
        time.sleep(1)
        print('')

    windows创建进程一定要在__main__中写,因为windows会将代码以模块的方式,从上往下执行一遍,而linux会直接将代码完完整整的拷贝一份。

    #以继承Process类的形式开启进程的方式
    from multiprocessing import Process
    import time
    class MyProcess(Process):
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run(self):
            print('%s is running'% self.name)
            time.sleep(3)
            print('%s is over'%self.name)
    
    if __name__ =='__main__':
        p = MyProcess('egon')
        p.start()
        print('')

    创建进程就是在内存中重新开辟一块内存空间,将允许产生的代码丢进去,一个进程对应在内存里的就是一块独立的内存空间。

    #进程间的数据是隔离的
    from multiprocessing import Process
    import time
    
    money = 100
    
    def test():
        global money  #  修改全局变量,通过这个来进行测试
        money = 99999
    
    if __name__ == '__main__':
        p = Process(target = test)
        p.start()
        p.join()
        print(money)
    
    >>>:100
    #创建的子进程和主进程是两个独立的空间,代码块是在子进程中执行的,所以只能修改子进程空间中的变量,主进程空间不受到影响

    进程对象以及一些方法

    join方法

    def f(name):
        print('hello',name)
        time.sleep(1)
        print('子进程在此')
    
    if __name__ == '__main__':
        p = Process(target=f,args=('bob',))
        p.start()  
        p.join()
        print('父进程在此')
    
    #start()它起到的作用的作用是让操作系统帮你创建一个进程,至于什么时候创建,由操作系统随机决定
    #当我们想让子进程先运行的时候我们可以用join,它的作用是让主进程等待子进程的运行结束

    terminate和is_alive

    from multiprocessing import Process,current_process
    import os
    import time
    
    def test(name):
        print('%s is running'%name,'子进程%s'%s.getpid(),'父进程%s'%os.getppid)
        time.sleep(3)
        print('%s is over'%name)
    
    if __name__ == '__main__':
        p = Process(targs=test,args=('egon',))
        p.start()
        p .termainate()  # 杀死当前进程
        time.sleep(0.1)
        print(p.si_alive)
        time.sleep(0.1)
        print(p.is_alive)  # 判断是否存活
        print('',os.getpid(),'主主进程%s'%os.getppid())

    守护进程

    from multiprocessing import Process
    import time
    
    def test(name):
        print('%s总管正常活着'%name)
        time.sleep(1)
        print('%s总管正常死亡'%name)
    
    if __name__ == '__main__':
        p = Process(target=test,args=('egon',))
        #p.daemon = True  # 守护进程,当主程序代码运行结束之后,守护进程随机终止
        p.start()
        time.sleep(0.1)
        print('皇帝jason寿终正寝')

    僵尸进程和孤儿进程

    僵尸进程:当进程结束之后还保留着一些信息以及它占用的PID,所有的进程都步入成僵尸进程。

      父进程回收子进程资源的两种方式

        1.join方法

        2.父进程正常死亡

    孤儿进程:子进程没死,但父进程意外死亡

         针对linux会有儿童福利院(init)如果父进程意外死亡他创建的子进程都会被福利院收养

    互斥锁

    多个程序操作用一份数据的时候会出现数据错乱的现象。

    避免的方法:将操作数据的部分加锁处理,会将并发变成串行牺牲了效率但是保证了数据的安全。

    #写一个简单的抢票系统
    from multiprocessing import Process,Lock
    import time
    import json
    
    #查询余票
    def search(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        print('用户%s查询余票为:%s'%(i,t_d.get('ticket')))
    
    #买票
    def buy(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        time.sleep(1)
        if t_d.get('ticket') > 0:
            t_d['ticket'] -= 1
            with open('data','w',encoding='utf-8') as f:
                json.dump(t_d,f)
            print('用户%s抢票成功'%i)
        else:
            print('没票了')
    
    def run(i):
        search(i)
        buy(i)
    
    if __name__ == '__main__':
        for i in range(10):  # 生成10个子进程去抢票
            p = Process(target=run,args=(i,))
            p.start()
    #这段代码运行之后会出现10个用户都抢到了票的情况,原因是每个用户拿的并不是一个实时的数据,所以在对数据进行修改时,所有人都在对拿到的数据进行修改,所以每个人都将自己拿到的票取了出来(程序中就是将数字减一)
    
    #怎么避免这种情况
    from multiprocessing import Process,Lock
    import time
    import json
    
    # 查票
    def search(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        print('用户%s查询余票为:%s'%(i,t_d.get('ticket')))
    
    # 买票
    def buy(i):
        with open('data','r',encoding='utf-8') as f:
            data = f.read()
        t_d = json.loads(data)
        time.sleep(1)
        if t_d.get('ticket') > 0:
            # 票数减一
            t_d['ticket'] -= 1
            # 更新票数
            with open('data','w',encoding='utf-8') as f:
                json.dump(t_d,f)
            print('用户%s抢票成功'%i)
        else:
            print('没票了')
    
    
    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()

    加锁之后,当一个进程拿到了这个数据的操作权限时,其它进程是无法对这个数据进行操作,甚至无法查看(就是当一个人抢到票在支付的时候其它人是看不到这张票的),其它进程只能等到这个进程的修改操作结束之后才能看到这个数据,然后也是要先抢到锁(所以一次只能有一个人),才能对数据进行修改,当这个进程结束对数据的操作要退出时,会释放锁,这时别的程序才能来抢锁,谁抢到谁来操作。

  • 相关阅读:
    【做题】51NOD1518 稳定多米诺覆盖——容斥&dp
    【做题】TCSRM592 Div1 500 LittleElephantAndPermutationDiv1——计数&dp
    【做题】TCSRM591 Div1 500 PyramidSequences——数形结合&思维
    【做题】NOWCODER142A Ternary String——数列&欧拉定理
    【做题】CF196E. Opening Portals 排除无用边&最小生成树
    【做题】HDU6331 Walking Plan——矩阵&分块
    【做题】BZOJ2534 L-gap字符串——调和级数
    【做题】BZOJ2342 双倍回文——马拉车&并查集
    overleaf 提交arXiv 不成功
    神经网络 (2)- Alexnet Training on MNIST
  • 原文地址:https://www.cnblogs.com/wangnanfei/p/11329697.html
Copyright © 2020-2023  润新知