• 网络并发编程


    网络并发编程的本质就是为了提升CPU的工作效率.

    操作系统发展史

    多道技术

    进程理论

    进程的并行与并发

    进程三状态

    同步与异步

    阻塞与非阻塞

    同步异步与阻塞非阻塞

    创建进/线程的两种方式

    join方法

    进程间默认数据隔离

    IPC机制

    生产者消费者模型

    查找进/线程相关方法

    守护进/线程

    僵尸进程与孤儿进程

    操作系统发展史

    计算机的三大核心硬件是: CPU, 内存, 硬盘. 其中CPU是整个计算机执行效率的核心

    操作系统经历了三个时代;
    1.穿孔卡片时代
    CPU的利用率非常低, 优点是一个人独占计算机.
    2.联机批处理系统
    缩短了录入数据的时间,提升了CPU利用率
    3.脱机批处理系统
    是现代计算机的雏形, 提升了CPU的利用率

    多道技术

    其前提是一个CPU
    单道技术是所有的程序排队执行, 总耗时是所有程序耗时之和.
    多道技术是计算机利用空闲时间提前准备好一些数据,提高效率, 总耗时较短.

    多道技术的特点是切换+保存状态
    1.CPU在两种状态下会切换去执行其他操作
    1.程序自身进入IO操作[IO操作: 输入输出操作, 获取用户输入, 读取文件,保存文件,time.sleep()等
    2. 程序长时间占用CPU.
    2. 保存状态 每次切换之前都要记录下当前执行的状态,之后切回来基于当前状态继续执行.

    进程理论

    进程: 正在被运行的程序
    进程的调度算法:
    1.先来先服务 >>> 对耗时较短的程序不友好
    2.短作业优先调度 >>> 对耗时长的程序不友好
    3.时间片轮转法+多级反馈队列
    将固定的时间均分成很多份,所有的程序来了都平分一份 >>> 分配多次之后如果还有程序需要运行, 则将其分到下一层 >>> 越往下表示程序总耗时越长,每次分的时间片越多则优先级越低.

    进程的并行与并发

    并行: 多个进程同时执行 , 需要有多个CPU
    并发:多个进程看上去像是同时执行就可以称之为并发, 单个CPU完全可以实现并发的效果, 如果是并行那么肯定也属于并发. >>>> 描述一个网站很厉害能同时服务很多人>>>> 这个网站能够支持14亿并发量(高并发) >>> 国内最厉害的网站>>>12306

    进程三状态

    就绪态: 所有程序被运行期都要经过就绪态(准备状态)
    运行态:运行过程中如果出现了IO操作,则进入阻塞态, 如果时间片段用完则继续进入就绪态
    阻塞态: 想要进入运行态就必须经过就绪态

    同步和异步

    用于描述人物的提状态
    同步: 提交完任务后原地等待任务结束, 不做任何事.
    异步: 提交完任务后不原地等待直接去做其他事情, 有了结果自动提醒.

    阻塞与非阻塞

    用于描述进程的执行状态
    阻塞为阻塞态
    非阻塞为就绪态或者运行态

    同步异步与阻塞非阻塞

    同步阻塞: 排队,并且在队伍中做什么都不做
    同步非阻塞; 排队, 在排队过程中做一些事情
    异步阻塞: 取号, 在旁边等待被叫号,期间什么也不做
    异步非阻塞: 取号,在旁边等待叫号,期间做想做的事.
    其中异步非阻塞状态下 CPU利用率最高.

    创建进程的两种方式

    1.双击桌面程序图标
    2.代码创建

    from multiprocessing import Process
    import time
    
    
    def task(name):
        print(f'{name}开始运行')
        time.sleep(3)
        print(f'{name}运行结束')
    
    if __name__ == '__main__':
        p = Process(target=task,args=('lili',))  # 创建一个进程对象
        p.start()  # 告诉操作系统创建一个进程(异步操作)
        # task('lili')   # 普普通通的函数调用是 同步操作
        print('主进程')  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    “”" 创建进程的代码在不同的操作系统中, 底层原理有区别.
    在Windows中, 创建进程类似于导入模块
    if name == ‘main’: 启动脚本在MAC,LINUX中创建进程类似于直接copy,不需要启动脚本, 但是为了兼容性, 也可以使用.“”"

    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run(self):
            print(f'{self.name}开始运行')
            time.sleep(3)
            print(f'{self.name}结束运行')
    
    if __name__ == '__main__':
        obj = MyProcess('lili')
        obj.start()
        print('主进程')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    创建进程的方式和创建现成的方式一致.

    同一进程下线程间数据共享

    我们将进程比作车间, 线程比作流水线, 那么同意车间内的资源是可以被不同流水线间共享的.

    from threading import Thread
    
    money = 1000
    
    
    def func():
        global money
        money = 666
    
    
    t = Thread(target=func)
    t.start()
    t.join()  # 确保线程运行完毕 再查找money 结果更具有说服性
    print(money)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    进程join方法

    join主进程等待子进程运行结束之后在运行

    直接在主进程代码里添加time.sleep()是不合理的, 因为无法准确把我子进程的执行时间
    使用join方法就会变得合理很多

    
    from multiprocessing import Process
    import time
    
    def task(name):
        print(f'{name}正在运行')
        time.sleep(3)
        print(f'{name}结束运行')
    
    if __name__ == '__main__':
        p1 = Process(target=task,args=('lili',1))
        p2 = Process(target=task,args=('pop',2))
        p3 = Process(target=task,args=('kim',3))
        start_time = time.time()
        p1.start()
        p2.start()
        p3.start()
        p1.join()
        p2.join()
        p3.join()
        end_time = time.time() - start_time
        print('总耗时:%s' %end_time)
        print('主进程')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    线程join方法

    主线程等到子线程运行结束之后再运行

    
    from threading import Thread
    import time
    
    def task():
        print('正在执行')
        time.sleep(3)
        print('运行结束')
    
    
    t = Thread(target=task)
    t.start()
    t.join()
    print('主线程')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    进程间默认数据隔离

    多个进程数据彼此之间默认相互隔离
    如果真的要交互,需要借助于’管道’或者’队列’

     from multiprocessing import Process
     ​money = 100
     ​​def task():    
    	 global money    
    	 money = 666    
    	 print('子进程打印的money', money)
     ​​if __name__ == '__main__':   
    	 p = Process(target=task)    
    	 p.start()    
    	 p.join()    
    	 print('父进程打印的money', money)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    IPC机制

    1.主进程与子进程通信
    2.子进程与子进程通信

    from multiprocessing import Queue,Process
    
    def procedure(q):
        q.put('子进程procedure往队列里添加了数据')
    
    
    def consumer(q):
        print('子进程consumer从队列里获取数据',q.get())
    
    
    if __name__ == '__main__':
        q = Queue()  # 在主进程中产生q对象,确保所有的子进程使用的是相同的q
        p1 = Process(target=procedure, args=(q,))
        p2 = Process(target=consumer, args=(q,))
        p1.start()
        p2.start()
        print('主进程')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    生产者消费者模型

    生产者: 产生数据
    消费者: 处理数据

    进程相关方法

    查看进程号

    from multiprocessing import current_process
    import os
    current_process().pid
    os.getpid()
    os.getppid()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    销毁子进程
    p1.terminate()
    判断进程是否存活
    p1.is_alive()

    线程相关方法

    1.进程号
    同一个进程下开设的多个线程拥有相同的进程号
    2.线程名
    from threading import Thread, current_thread
    current_thread().name
    主:MainThread 子:Thread-N
    3.进程下的线程数
    active_count()

    守护进程

    伴随着守护对象的存活而存活 死亡而死亡

    from multiprocessing import Process
    import time
    
    
    def task(name):
        print('用户a:%s存活' % name)
        time.sleep(3)
        print('用户a:%s消失' % name)
    
    
    if __name__ == '__main__':
        p = Process(target=task, args=('基佬',))
        # p.daemon = True  # 将子进程设置为守护进程:主进程代码结束 子进程立刻结束
        p.start()
        p.daemon = True  # 必须在start之前执行
        print('主进程结束!!!')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    守护线程

    守护线程伴随着被守护的线程的结束而结束

    from threading import Thread
    import time
    
    def task():
        print('子线程运行task函数')
        time.sleep(3)
        print('子线程运行task结束')
    
    
    t = Thread(target=task)
    # t.daemon = True
    t.start()
    # t.daemon = True
    print('主线程')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    进程下所有的非守护线程结束 主线程(主进程)才能真正结束!!!

    僵尸进程与孤儿进程

    僵尸进程: 进程已经运行结束,单数相关资源并没有完全清空, 需要父进程参与回收
    孤儿进程: 父进程意外死亡,子进程正常运行,操作系统会自动回收相关资源.

    本文全是理论, 只为科普一些基本的概念.
    在这里插入图片描述

  • 相关阅读:
    2022年9月改名字这件事的流程亲历和体会
    Web3去中心化存储生态图景
    JDK多版本切换
    Addressing Failure Prediction by Learning Model Confidence
    力扣学习笔记——49. 字母异位词分组
    Cookie和Session
    grid弹性布局 设置宽高一致
    【Java】数组详解
    VS2015 Winform 添加文件后 中文乱码
    Enscape 4.1.0 软件安装教程+离线资源库
  • 原文地址:https://blog.csdn.net/weixin_67531112/article/details/126331637