• GIL 相关 和进程池


    #GIL  (global interpreter Lock)

    #全局解释器锁 :锁是为了避免资源竞争造成数据错乱

    #当一个py启动后 会先执行主线程中的代码
    #在以上代码中有启动了子线程 子线程的任务还是执行代码
    #解释器在一个进程中只有一个(解释器也是一堆代码)
    #主线和子线都要去调用解释器,就存在了竞争关系



    #全局解释器锁: 是为了防止多个线程同时使用python解释器 一旦加锁 将导致线程无法并行
    #这个问题不是所有解释器都存在 只有cpython(c写的解释器) 也就是说只有cpythonzhong
    #有全局解释器锁 如果是Jpython 就要参考Java的多线程实现
    #python程序的执行:
    #1.启动解释器进程 python.exe
    #2.解析py文件并执行它

    # 每个py程序中都必须有解释器参与 解释器其实就是一堆代码
    #相当于多个线程要调用同一个解释器代码 共享变成竞争 竞争就要出事 给解释器加互斥锁

    # python中内存管理依赖于GC(一段用于回收内存的代码) 也需要一个线程 除了自己开的线
    # 程 系统还有一些内置线程 就算你的代码不会去竞争解释器 内置线程也可能会竞争 所以
    # 所以必须加上锁

    #当一个线程遇到了IO 同时解释器也会自动解锁 去执行其他线程 cpu会切换到其他程序
    # 案例:
    # from threading import Thread
    # import time
    # def task1():
    # sum=1
    # for i in range(10000000):
    # sum+=i
    # def task2():
    # sum=1
    # for i in range(10000000):
    # sum+=i
    # start=time.time()
    # t1=Thread(target=task1)
    # t2=Thread(target=task2)
    # t1.start()
    # t2.start()
    # t1.join()
    # t2.join()
    # print(time.time()-start)

    #解释器加锁以后:
    #将导致所有线程只能并发 不能达到真正的并行 意味着同意时间只有一个cpu在处理你的
    #线程 给你的感觉是小路低

    #代码执行有两种状态;
    #阻塞 i/o :失去cpu的执行权 (cpu等待I/O完成)
    #非阻塞 :代码正常执行 比如循环一千万次 中途cpu可能切换 但是很快会回来(cpu在计算)

    #加入有32核cpu 要处理一个下载任务 网络速度慢 100k/s 文件大小为1024kb 如果你的代码中
    #IO操作非常多 cpu性能不能直接决定你的任务处理速度

    #案例:
    #目前有三个任务 每个任务处理需要一秒 获取元数据需要一小时
    #3个cpu 需要一小时一秒
    #1个cpu 需要一小时三秒

    #在IO密集的程序中 cpu性能无法直接决定程序的执行速度 python就应该干这种活儿
    #在计算密集的程序中 cpu性能可以直接决定程序的执行效率



    #2.GIL与互斥锁
    #GIL与互斥锁:
    # from threading import Thread,Lock
    # import time
    # mutex=Lock()
    # num = 1
    # def task():
    # global num
    # mutex.acquire()
    # temp=num
    # time.sleep(1) #当线程中出现io时 GIL锁就解开了
    # num=temp+1
    # mutex.release()
    # t1=Thread(target=task,)
    # t2=Thread(target=task,)
    # t1.start()
    # t2.start()
    # t1.join()
    # t2.join()
    # print(num)
    # #GIL和自定义互斥锁的区别
    # #全局锁不能保证自己的线程安全 但是保证解释器中的数据安全
    # #GIL在线程调用解释器时 自动加锁 IO阻塞时和线程代码执行完毕时 自动解锁
    #
    #3.线程池与进程池
    # 进程池: 就是一个装进程的容器
    # 为什么出现: 当进程很多的时候方便管理进程
    # 什么时候用:当并发量特别大的时候 例如双十一 很多时候进程是空闲的 就让他进入进程池
    #让有任务处理的进程进入进程池
    # 进程池:
    # ProcessPoolExecutor
    # 创建时指定最大进程数 自动创建进程
    # 调用submit函数将任务提交到进程池中
    # 创建进程是在调用submit后发生的
    #举例:
    # #收发数据
    # def task(c,addr):
    # while True:
    # data=c.recv(1024)
    # print(data.decode("utf-8"))
    # if not data:
    # c.close()
    # break
    # c.send(data.upper())
    # if __name__ == '__main__':
    # import socket
    # from concurrent.futures import ProcessPoolExecutor
    # server=socket.socket()
    # server.bind(("127.0.0.1",8091))
    # server.listen(5)
    # #创建一个进程池 默认
    # pool=ProcessPoolExecutor()
    # while True:
    # c,addr = server.accept()
    # pool.submit(task,c,addr)

    #总结一下:
    # 进程池可以自动创建进程
    # 进程限制最大进程数
    # 自动选择一个空闲的进程帮你处理任务
  • 相关阅读:
    动态添加LInk的分析
    ASP.NET内置对象-网页转向的4中方法
    网页生命周期-动态添加控件
    网页生命周期-控件事件执行顺序
    网页生命周期-PageLoad事件
    HyperLink 控件
    ListBox控件
    OptionMenu选项菜单
    Menubutton按钮弹出菜单
    Menu-右键弹出菜单
  • 原文地址:https://www.cnblogs.com/yanhui1995/p/9945764.html
Copyright © 2020-2023  润新知