• 进程,线程和协程


    概念

    进程:进程是一种抽象概念。是计算机资源分配的最小单元。由程序,数据集合和进程控制块(PCB,保存进程的描述和控制信息,也是进程存在的标识)。白话叫执行一个程序系统就开辟一个独立的内存块。系统分配资源按照进程为单位。

    线程:轻量级进程,是系统调度最小单位。因为进程切换开销很大,发明了线程。一个进程有一个或者多个线程

    协程:基于线程之上,更轻量级的存在,由程序员自己调度的用户线程。发生在用户态对内核不可见。减少上下文切换提高效率。

    GIL:全局解释器锁。为了数据安全(指进程的数据安全,防止多线程执行过程中对进程数据和指令的破坏)每个cpu(超线程,一物理cpu能分成俩虚拟的)只能执行一个线程。只有获取到GIL锁的线程才能执行。python2里通过一个计数器ticks到100了就切换。(所以多线程关于cpu计算密集型任务不友好,一个线程一直在计算也没办法切换,那用多线程干啥呢)python3中换成了时间计数器,过一段时间就换。

    python中的多进程代码

    import os, time
    from multiprocessing import Process, Queue, Pool, Manager
    
    
    
    def run_pro(name:str, q:Queue):
        pid = os.getpid()
        q.put(pid)
        print("running process %s", name)
        time.sleep(3)
        print("done with %s", name)
    
    
    def main():
        // 注释部分为调用Process进行多进程
        # q = Queue()
        q = Manager().Queue()    // 利用进程池时,要用这个Q
        # p1 = Process(target=run_pro, args=("p1", q))
        # p2 = Process(target=run_pro, args=("p2", q))
        # p1.start()
        # p2.start()
        # print(q.get(timeout=120, block=True))  // 超时时间和是否阻塞
        # print(q.get(timeout=120, block=True))
        # p1.join()                              // 子进程加入到主进程,即主进程执行完等子进程
        # p2.join()
        pool = Pool(4)                           // 若进程只有4个任务有10个,则要等进程执行完
        for i in range(10):
            pool.apply_async(run_pro, args=(str(i), q))      // aplly 是同步执行
        pool.close()
        pool.join()
    
    
    if __name__ == '__main__':
        main()
    

    多线程的基本调用和多进程基本类似,并提供互斥锁等保护线程安全

    进程之间的通信

    代码中用到了q,python中还可以用pipe。在Linux中进程通信方式有:信号,信号量,socket(套接字,域名协议端口),共享内存,数据库,管道等python中都有响应的模块实现

    协程

    Python对协程的支持是通过generator实现的。函数中有关键字yeild称为生成器,generator。

    1 import random
    2
    3
    4 def cuns():
    5 	 n = 10
    6 	 while True:
    7 		 print("n", n)
    8 		 n = yield random.randrange(0, n)
    9 
    10
    11def pro(c):
    12	print("start")
    13	c.send(None)
    14	print("start send")
    15	req = c.send(4)
    16	print("req", req)
    17	c.close()
    
    
    if __name__ == '__main__':
    	c = cuns()
    	pro(c)
    
    • 通过调用next()或者send()方法调用生成器

    • 每调用一次代码走到下一个yield之前,故第一次调用不返回,并且send方法第一次调用参数是None

    • send的参数即是yeild的前边的变量,代码8行

    • 正常的生成器走完抛出StopIteration错误,也可使用close方法关闭

    异步

    异步是利用了协程的原理(下文代买来自网络)

    import requests, time, asyncio
    async def test2(i):
        r = await other_test(i)
        print(i,r)
    async def other_test(i):
        r = requests.get(i)
        print(i)
        await asyncio.sleep(4)
        print(time.time()-start)
        return r
    
    url = ["https://segmentfault.com/p/1210000013564725",
           "https://www.jianshu.com/p/83badc8028bd",
           "https://www.baidu.com/"]
    
    loop = asyncio.get_event_loop()
    task = [asyncio.ensure_future(test2(i)) for i in url]
    start = time.time()
    loop.run_until_complete(asyncio.wait(task))
    endtime = time.time()-start
    print(endtime)
    loop.close()
    
    • 异步的语法糖async 和 await需要配合使用
    • 在async中的await方法后接awaitable的函数,否则报错
    • asyncio模块提供时间循环get_even_loop时间循环支持多个异步函数
    • 另loop事件循环支持call_back回调函数
    • asyncio的Feature也是awaitable
  • 相关阅读:
    VS2010开发C的方法
    Activity.startManagingCursor方法
    application/xwwwformurlencoded、multipart/formdata、text/plain
    TCP三次握手/四次挥手详解
    hdu 2157 How many ways??
    zoj 2475 Benny's Compiler
    zoj 2744 Palindromes
    zoj 2750 Idiomatic Phrases Game
    zoj 2104 Let the Balloon Rise
    flash:学习ActionScript的一些提示
  • 原文地址:https://www.cnblogs.com/khal-Cgg/p/14621902.html
Copyright © 2020-2023  润新知