• 多进程,进程池,协程


    多进程

    并行,同时执行。 一个程序运行起来之后,代码用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的

    进程之间是相互独立的

    cpu计算密集的时候适合用多进程

    有几核CPU就可以同时执行几个进程

    开启进程需要调用 multiprocessing 模块

    import multiprocessing      #调用进程模块
    import time
    def test1():
        for i in range(5):
            time.sleep(1)
            print('test', i)
    def test2():
        for i in range(5):
            time.sleep(1)
            print('test', i)
    
    if __name__ == '__main__':      #固定格式(必须加)后面的执行代码要缩进
        p1 = multiprocessing.Process(target=test1)  #添加一个test1变成一个子进程赋值给p1
        p2 = multiprocessing.Process(target=test2)
        p1.start()      #开启p1子进程
        p2.start()
    

     结果:

    #停顿一秒
    test 0
    test 0
    #停顿一秒
    test 1
    test 1
    #停顿一秒
    test 2
    test 2
    #停顿一秒
    test 3
    test 3
    #停顿一秒
    test 4
    test 4
    

     进程之间不共享,相互独立

    import multiprocessing
    g_num = 0
    def edit():
        global g_num
        for i in range(10):
            g_num += 1
        print(g_num)
    def reader():
        print(' ')
        print(g_num)
    
    if __name__ == '__main__':
        p1 = multiprocessing.Process(target=edit)
        p2 = multiprocessing.Process(target=reader())
        p1.start()
        p2.start()
        print(g_num)
    
    结果:

    全局变量没有被改变

    0 
    0
    10
    进程池的并发

    apply_async 是异步非阻塞的。即不用等待当前进程执行完毕,随时根据系统调度来进行进程切换。首先主进程开始运行,碰到子进程后,主进程仍可以先运行,等到操作系统进行进程切换的时候,在交给子进程运行。可以做到不等待子进程执行完毕,主进程就已经执行完毕,并退出程序。

    import multiprocessing      #调用进程模块
    from multiprocessing import Pool    #调用进程池模块
    import time
    import threading
    g_num = 0
    def test1():
        for i in range(10):
            time.sleep(1)
            print('test1', i)
    
    def test2():
        for i in range(10):
            time.sleep(1)
            print('test2', i)
    
    def test3():
        for i in range(10):
            time.sleep(1)
            print('test3', i)
    
    
    if __name__ == '__main__':
        pool = Pool() #括号里写几就代表可以允许同时执行几个进程,不写的话就按照cpu的各项指标系统分配同时执行的进程数。
        pool.apply_async(test1) ##维持执行的进程,当一个进程执行完毕后会添加新的进程进去
        pool.apply_async(test2)
        pool.apply_async(test3)
        pool.close()    #关闭进程池,表示不能再往进程池中添加进程,需要在join之前调用
        pool.join()     #等待进程池中的所有进程执行完毕

    进程包括线程(线程是轻量级的)

    线程包括协程(协程是微量级的)

    协程比线程更加适合IO密集的操作

    协程

    协程,又称微线程,纤程。英文名Coroutine。 首先我们得知道协程是啥?协程其实可以认为是比线程更小的执行单元。 为啥说他是一个执行单元,因为他自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

    那么这个过程看起来和线程差不多。其实不然, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

    需要调用 gevent 模块,第三方模块,需要pip下载。

    import gevent,time
    from gevent import monkey
    monkey.patch_all()
    def test1():
        for i in range(10):
            time.sleep(1)
            print('1===>', i)
    
    def test2():
        for i in range(10):
            time.sleep(2)
            print('2===>', i)
    
    g1 = gevent.spawn(test1)
    g2 = gevent.spawn(test2)
    g1.join()
    g2.join()

    因为第一个协程挺一秒,第二个协程停2秒,所以CPU一个时间段内执行两次协程1,一次协程2

    1===> 0
    2===> 0
    1===> 1
    1===> 2
    2===> 1
    1===> 3
    1===> 4
    2===> 2
    2===> 3
    2===> 4
  • 相关阅读:
    vue 中的键盘事件
    红米k40刷类原生系统
    (历史) 1960s,大家争先在共享内存上实现原子性 (互斥) 但几乎所有的实现都是错的,直到 Dekker's Algorithm,还只能保证两个线程的互斥
    Go Memory Model 内存模型 同步 goroutine
    理解并发程序执行 (Peterson算法、模型检验与软件自动化工具
    源码 连接池 设计
    Thread Exception Captured Application Crash Report
    Check if the context is expired.
    A Quick Guide to Go's Assembler
    敏感问题调查 干扰变量 抛硬币
  • 原文地址:https://www.cnblogs.com/dayle/p/10028617.html
Copyright © 2020-2023  润新知