• 并发进程


    1.计算机硬件和操作系统

    1. 计算机硬件组成:
      • 主板:固化(寄存器,是直接和cpu进行交互的一个硬件)
      • cpu:中央处理器,能够进行数学运算和一些逻辑运算,并且控制所有硬件协调工作
      • 存储:硬盘和内存
      • 输入设备:键盘,鼠标,话筒
      • 输出设备:显示器,音响,打印机
    • 早期的计算机是以计算为核心的
    • 现在的计算机是以存储为核心的

      2.计算机操作系统:

      • 操作系统是一个软件,是一个能直接操纵硬件的一个软件
      • 它的目的是让用户用起来更加的轻松,高可用,低耦合;
      • 几个代表性系统:dos  windows unix

    操作系统的作用:

    • 封装所有硬件接口,让各种用户使用电脑更加轻松;
    • 是对计算机内所有的资源进行合理的调度和分配; 

    2.进程的理论

    1. 几个后缀文件:
      • .sh  shell脚本文件
      • .out linux系统中的可执行文件
      • .bat 批处理脚本文件
      • .lib 库文件
      • .dll 库
      • .exe 可执行文件

      2.进程:

      • 是指正在执行的程序;
      • 是程序执行过程中的一次指令
      • 也可以叫做程序的一次执行过程
      • 进程是一个动态的概念

      3.进程三大部分组成:代码段,数据段,PCB:进程管理调度

      4.进程的三大基本状态

      • 就绪状态:已经获得运行需要的所有资源,除了cpu
      • 执行状态:已经获得了所有资源包括cpu,处于正在执行
      • 阻塞状态:因为各种原因,进程放弃了cpu,导致进程无法继续执行;此时进程处于内存中,继续等待获取cpu
      • 因为各种原因,进程放弃了cpu,导致进程无法继续执行,此时进程被踢出内存;

    3.关于进程的一些名词

    • 并行:是指两者同时执行,一定是多个车道,在同一时间点
    • 并发:是指在资源有限的情况下,两者轮流使用资源,只有一条赛道
    • 同步:就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,才能继续进行,是可靠的任务序列,要么成功都成功,失败都失败,两个任务的状态可以保持一致;
    • 异步:不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也会立即执行,至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠序列;
    • 同步:比如你去商店买书,你问老板有没有<古龙小说集>,老板说我给你查查,然后你就一直等,有可能等一天,有可能等一个小时,必须等到一个结果,你才去进行下一步;
      
      异步:还是你去买书,你问老板有没有,老板说,你先回去吧,我帮你查查,有了电话通知你,你得到一个结果,可是这个结果并不是真实的结果,只是一个反馈结果而已;
      
      阻塞:还是买书,你问老板有没有,老板说我帮你查查,然后你会一直在等,等到天荒地老,什么也不干,等一个结果;
      
      非阻塞:还是买书,你问老板有没有,老板说我帮你查查,你说老板你先查着,我先玩一会,然后你一会在过来看看;
      例子
    • 阻塞与非阻塞:阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的
    • 同步阻塞形式
        效率最低。拿上面的例子来说,就是你专心排队,什么别的事都不做。
      
      异步阻塞形式
        如果在银行等待办理业务的人采用的是异步的方式去等待消息被触发(通知),也就是领了一张小纸条,假如在这段时间里他不能离开银行做其它的事情,那么很显然,这个人被阻塞在了这个等待的操作上面;
      
        异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞。
      
      同步非阻塞形式
        实际上是效率低下的。
      
        想象一下你一边打着电话一边还需要抬头看到底队伍排到你了没有(两个操作不能同时执行,因为是同步),如果把打电话和观察排队的位置看成是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的。
      
      异步非阻塞形式
        效率更高,
      
        因为打电话是你(等待者)的事情,而通知你则是柜台(消息触发机制)的事情,程序没有在两种不同的操作中来回切换。
      
        比如说,这个人突然发觉自己烟瘾犯了,需要出去抽根烟,于是他告诉大堂经理说,排到我这个号码的时候麻烦到外面通知我一下,那么他就没有被阻塞在这个等待的操作上面,自然这个就是异步+非阻塞的方式了。
      四个名词

    4. multiprocessing.Process模块

    1.进程两种开启方式:实例化一个进程的对象:

    def func():
        print('子进程1的爸爸是%s,我是%s' % (os.getppid(),os.getpid()))
    def func2():
        print('子进程2的爸爸是%s,我是%s' % (os.getppid(), os.getpid()))
    
    if __name__ == '__main__':
        li = [func, func2]
        for i in li:
            p = Process(target=i)
            p.start()
        print('主进程的爸爸是%s,我自己是%s' % (os.getppid(),os.getpid()))
    
    #主进程的爸爸是1116,我自己是12760
    子进程1的爸爸是12760,我是848
    子进程2的爸爸是12760,我是11588
    • Process类的介绍:强调需要使用关键字的方式指定参数(target=None,args=None,kwargs=None)
    • 参数介绍:
      • target:表示调用对象,即子进程要执行的任务
      • args:表示调用对象的位置参数元组,
      • kwargs:表示调用对象的字典
    • 方法注意:
      • p.join([timeout]):主线程等待p终止,timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程

    2.通过继承

    class Myprocess(Process):
        def __init__(self,name):
            super(Myprocess, self).__init__()
            self.name = name
        def run(self):
            print('这是以继承类的方式开启的子进程%s,他的名字是%s' %(os.getppid(),self.name))
    
    if __name__ == '__main__':
        p = Myprocess('alex')
        p.start()
        print('这里是主进程%s' % os.getpid())

    3.进程的常用方法

    1. start() 开启一个子进程
    2. join() 异步变同步(就是让父进程停留在join这句话,等待子进程执行结束)
    3. is_alive()判断进程是否还活着
    4. terminate()杀死进程

    每个方法的代码演示:

    from multiprocessing import Process
    import time
    
    def func():
        for i in range(500):
            time.sleep(0.01)
            print('儿子在这里')
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.join()# 是让主进程等待子进程执行完。  现象:主进程执行到这句话,主进程阻塞住,等待子进程执行
        for i in range(100):
            time.sleep(0.01)
            print('爸爸在这里')
    
    # 开启一个正常的子进程,父进程会等待子进程结束后,父进程也就是程序才结束
    # p.join()# 是让主进程等待子进程执行完。  现象:主进程执行到这句话,主进程阻塞住,等待子进程执行
    # 如何把父进程和子进程之间的关系变为同步或者异步?
    # 父进程执行join,就会变成同步,不执行join,父进程和子进程就是异步的关系
    # join必须放在start()后边
    join和start
    from multiprocessing import Process
    import time
    
    
    def func():
        time.sleep(1)
        print(123)
    
    
    if __name__ == '__main__':
        p = Process(target=func,)
        p.start()
        p.terminate()# 杀死p进程,让解释器告诉操作系统,请杀掉p进程。
        print('子进程是否还活着?', p.is_alive())
        time.sleep(0.002)
        print('子进程是否还活着?', p.is_alive())
        # 返回一个bool值,如果返回True,代表进程还活着,如果返回False,代表子进程死了
    
    # p.is_alive() 判断p进程是否还活着
    # p.terminate() 杀死p进程
    is_alive和terminate
    def func():
        print(111)
    if __name__ == '__main__':
        # server()
        p = Process(target=func,args=())
        p.start()
        p.terminate()
        #因为你的代码只是给操作系统发信号,但是操作系统什么时间执行控制不了
        #所以有可能主进程先被执行完了,但是terminate没有is_alive执行的快
        print(p.is_alive())
        print(333)
    #输出结果
    True     #应该为false,,为什么True,请看上面解释
    333

    4.进程的常用属性

    • p.name = 给p进程的一个名字
    • p.pid = 返回p进程的pid
    • p.daemon = True 将p进程设置为守护进程(True为守护进程,False为普通进程)
      • 守护进程的两个特点:
      • 守护进程会随着父进程的代码执行结束而结束
      • 守护进程不能再创建子进程(不能有孩子)
    from multiprocessing import Process
    import time
    
    def func1():
        for i in range(65,90):
            print(chr(i))
            time.sleep(0.5)
    
    def func():
        for i in range(10):
            print(i)
            time.sleep(0.5)
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()           #开启一个普通进程
        p1 = Process(target=func1)
        #守护进程在p1.start()要开启时,下面没有代码段了,这代表主进程没有代码段了
        #所以守护进程没有运行就结束了
        p1.daemon = True
        p1.start()          #开启一个守护进程
    #输出结果:
    0 1 2 3 4 5 6 7 8 9
    守护继承的特性上
    from multiprocessing import Process
    import time
    
    def func1():
        for i in range(65,90):
            print(chr(i))
            time.sleep(0.5)
    
    def func():
        for i in range(10):
            print(i)
            time.sleep(0.5)
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()           #开启一个普通进程
        p1 = Process(target=func1)
        #守护进程在p1.start()要开启时,下面没有代码段了,这代表主进程没有代码段了
        #所以守护进程没有运行就结束了
        p1.daemon = True
        p1.start()          #开启一个守护进程
        time.sleep(2)       #父进程代码段没有结束,守护进程才会执行,
        #A 0 1 B C 2 D 3 4 5 6 7 8 9
    守护进程的特性下
    from multiprocessing import Process
    import time
    def func():
        for i in range(10):
            time.sleep(1)
            print(time.strftime("%H:%M:%S"))
    if __name__ == '__main__':
        #设置为守护进程后,会根据主进程想要的效果停止的子进程
        p = Process(target=func)
        p.daemon = True
        p.start()
        time.sleep(5)
        print('计时结束!')
    #输出结果
    20:15:49
    20:15:50
    20:15:51
    20:15:52
    20:15:53
    20:15:54
    计时结束!
    守护进程的作用
    from multiprocessing import Process
    import time
    import os
    
    def func():
        print('这里是儿子,儿子的pid是%s'%(os.getpid()))
    
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.name = 'alex'
        print('儿子的名字是%s'%p.name)
        print('儿子的pid是%s'%p.pid)
        print('儿子是不是守护进程?',p.daemon)
    其他属性
  • 相关阅读:
    SQL 操作结果集 -并集、差集、交集、结果集排序
    MongoDB系列四:解决secondary的读操作
    org.apache.hadoop.ipc.RemoteException: User: root is not allowed to impersonate root
    hive 中窗口函数row_number,rank,dense_ran,ntile分析函数的用法
    FormData上传文件同时附带其他参数
    Hive删除分区
    Hive日期格式转换用法
    HIVE 不支持group by 别名
    ODS与EDW的区别
    hive数据类型转换、字符串函数、条件判断
  • 原文地址:https://www.cnblogs.com/0627zhou/p/9507831.html
Copyright © 2020-2023  润新知