zoukankan      html  css  js  c++  java
  • 网络编程之并发

    操作系统:
    第一代计算机:真空管,穿孔卡片
    没有操作系统,直接操作硬件
    优点:程序员独享计算机资源,可以及时调试bug
    缺点:计算机资源浪费,当程序员出现bug调试时,计算机闲置
    第二代计算机:晶体管,批处理系统
    针对第一代计算机的缺点:
    1.将多人的程序攒成一波输入
    2.顺序计算,串行
    3.将多个程序的运行结果攒成一波输出
    优点:提高了计算机利用率
    缺点:程序员需等待一波输入的结果出来后才能知道自己的程序运行结果,出bug了也无法及时的调试
    需要人控制
    串行,按顺序执行
    第三代计算机:集成电路芯片和多道程序
    多道技术:当只有一个cpu时
    多道技术:①操作系统将程序读入内存,内存中可放入多个程序
    ②cpu在程序中切换执行,提高了cpu利用率
    cpu在两种情况下会切换:①当程序遇到IO时②当执行一个程序过长时

    多道技术中的多道指的是多个程序,多道技术的实现是为了解决多个程序竞争或者说共享同一个资源(比如cpu)的有序调度问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用。
    空间上的复用:多个程序占用的内存空间是相互分离的
    时间上的复用:cpu在执行一个程序过长或程序遇到IO操作时会切换

    进程,程序
    程序:一堆文件
    进程:运行中的程序
    并发:cpu在多个程序间切换执行,给人一种多个程序在同时执行的感觉,单核
    并行:多个程序同时执行,叫并行
    子进程:
    当执行程序时遇到程序无法执行的任务需开启另一个进程,则被开启的进程称为子进程
    创建子进程的两种方法:

    #第一种
    from multiprocessing import Process
    
    def task():
        print("子进程run")
    
    if __name__ == "__main__":
        p = Process(target = task)
        p.start()
        print("主进程run")
    #第二种
    from multiprocessing import Process
    # 创建进程的第二种方式  继承Process  覆盖run方法
    # 在子进程启动以后会自动执行run方法
    # 其优势是 可以自定义 进程的属性和行为 来完成一些额外任务 例如下载
    # class MyProcess(Process):
    #
    #     def __init__(self,url):
    #         self.url = url
    #         super().__init__()
    #
    #     # 子类中的方法  只有run会被自动执行
    #     def run(self):
    #         print("下载文件...." , self.url)
    #         print(" run run run!")
    #
    #     def task(self):
    #         pass
    #
    # def task():
    #     print(123)
    
    # if __name__ == '__main__':
    #     p = MyProcess("www.baidu.com/xx.mp4")
    #     p.start()   
    

    windows 和unix系统创建的子进程:

    window:子进程和主进程有独立的内存空间,子进程会copy主进程中的代码,如果我们不将创建子进程的操作放入if__name__==“main”下的话,子进程导入主进程时也会执行创建子进程的操作,导致无限循环的创建子进程

    unix:
    在UNIX中,子进程的初始地址空间是父进程的一个副本,提示:子进程和父进程是可以有只读的共享内存区的。但是对于windows系统来说,从一开始父进程与子进程的地址空间就是不同的。

    进程的三种状态:就绪,阻塞,运行
    由于CPU的切换机制,我们想提高我们程序的执行效率的话,需要尽量减少IO操作,使我们的程序多处于就绪态

    子进程的join方法
    join方法,当我们需要在所有子进程执行完毕后再执行主进程时,就需要使用join方法了

    #不加join
    from multiprocessing import Process
    import time
    def task(n):
        print(n)
        time.sleep(6-n)
        print("子进程%s运行完毕"%n)
    
    if __name__ == '__main__':
        for i in range(5):
            p = Process(target=task, args=(i,))
            p.start()
        print("父进程运行完毕")
    #执行结果
    #父进程运行完毕
    # 0
    # 1
    # 2
    # 3
    # 4
    # 子进程4运行完毕
    # 子进程3运行完毕
    # 子进程2运行完毕
    # 子进程1运行完毕
    # 子进程0运行完毕
    #p.start()是向操作系统发起请求开启子进程,开启子进程是需要时间的,然后会进行下一次循环,(经测验我的计算机循环20次,子进程会起来),此时循环5次后,子进程并未起来,故此时先打印父进程执行完毕
    
    #在for循环内使用join
    def task(n):
        print(n)
        time.sleep(6-n)
        print("子进程%s运行完毕"%n)
    
    
    if __name__ == '__main__':
        for i in range(5):
            p = Process(target=task, args=(i,))
            p.start()
            p.join()
        print("父进程运行完毕")
    #执行结果
    # 0
    # 子进程0运行完毕
    # 1
    # 子进程1运行完毕
    # 2
    # 子进程2运行完毕
    # 3
    # 子进程3运行完毕
    # 4
    # 子进程4运行完毕
    # 父进程运行完毕
    #对每一个子进程都提高它的优先级,相当于串行了
    
    #3.在for循环外进行join
    def task(n):
        print(n)
        time.sleep(6-n)
        print("子进程%s运行完毕"%n)
    if __name__ == '__main__':
        for i in range(5):
            p = Process(target=task, args=(i,))
            p.start()
        p.join()
        print("父进程运行完毕")
    #执行结果
    #0
    # 1
    # 2
    # 3
    # 4
    # 子进程4运行完毕
    # 父进程运行完毕
    # 子进程3运行完毕
    # 子进程2运行完毕
    # 子进程1运行完毕
    # 子进程0运行完毕
    #相当于对最后一个子进程提升优先级,它执行完成后,父进程就会执行
    
    #4.使用for循环join
    from multiprocessing import Process
    import time
    def task(n):
        print(n)
        time.sleep(6-n)
        print("子进程%s运行完毕"%n)
    if __name__ == '__main__':
        ps = []
        for i in range(5):
            p = Process(target=task, args=(i,))
            p.start() 
            ps.append(p)
        for p in ps:
            p.join()
        print("父进程运行完毕")
    #执行结果
    # 0
    # 1
    # 2
    # 3
    # 4
    # 子进程4运行完毕
    # 子进程3运行完毕
    # 子进程2运行完毕
    # 子进程1运行完毕
    # 子进程0运行完毕
    # 父进程运行完毕
    #循环增加子循环的优先级,确保父进程在所有子进程完成后才会执行,与第二种方法的区别,子进程的启动是并发的,第二种方法就是串行,无并发可言
    

    子进程的其他方法和属性
    p1.terminate()#关闭进程,不会立即关闭,所以is_alive立刻查看的结果可能还是存活
    print(p1.is_alive()) #判断子进程是否在运行中,结果为True

    僵尸进程和孤儿进程
    孤儿进程:
    正常运行程序时,主进程会在所有子进程结束后才会停止运行,
    因为父进程需要清除子进程的残留信息,
    那为什么子进程运行结束后不自行清除残留信息,
    因为父进程需要在其未终止的任何时刻都能拿到子进程的pid和属性信息,所以不能让子进程自己消除,而是父进程来消除(使用join方法会清除子进程信息)
    那么如果子进程未运行结束,父进程被干死了,此时的子进程称为孤儿进程,操作系统会接手,清除孤儿进程的残留信息,故孤儿进程是无害的
    僵尸进程:
    父进程没有关闭,子进程运行结束后,会残留pid和属性信息,占用系统内存,称为僵尸进程,当僵尸进程过多时会导致过多占用pid和系统内存,僵尸进程是有害的

  • 相关阅读:
    测试SQL
    UpdatePanel中弹出新窗口
    无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever
    Repeater嵌套Repeater
    SQL2000清除SQL日志
    sql批量修改字段内容的语句-SQL技巧
    SQL时间格式化 转载备用~
    远程连接数据库
    MySql 文件导入导出
    pyspark启动与简单使用----本地模式(local)----shell
  • 原文地址:https://www.cnblogs.com/robert-zhou/p/10197498.html
Copyright © 2011-2022 走看看