0

Python高级 | 多进程多线程

 5 months ago
source link: https://jiac3366.github.io/2021/12/20/Python%E9%AB%98%E7%BA%A7/%E5%A4%9A%E8%BF%9B%E7%A8%8B%E5%A4%9A%E7%BA%BF%E7%A8%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

+c编程手记

Guangzhou, China
  • 多进程多线程

    • threading

      • run()触发你传入的函数
      • 当I/O 操作非常多、非常 heavy、需要建立的连接也比较多的时候,一般会创建挺多的线程,但线程池线程数一般有一个建议数值。但是协程对于这种场景可以创建很多的协程数量来应对,防止线程池不够用的场景。
      • 为什么有 GIL?和 CPython 的实现有关

        GIL,CPython 解释器 中1个技术术语

        • 1、防止使用多个线程被分配到多个CPU执行用一份代码(?造成内存管理的引用计数发生race condition
          CPython 使用引用计数来管理内存,如果有两个 Python 线程同时引用了 a,就会造成引用计数的 race condition,引用计数可能最终只增加 1,这样就会造成内存被污染。因为第一个线程结束时,会把引用计数减少 1,这时可能达到条件释放内存,当第二个线程再试图访问 a 时,就找不到有效的内存了。

        • 2、CPython 大量使用 C 语言库,但大部分 C 语言库都不是原生线程安全的(线程安全会降低性能和增加复杂度)。

      • GIL如何工作:

        每一个线程在开始执行时,都会锁住 GIL,以阻止别的线程执行

        • CPython 中有个check_interval机制 ,去轮询检查线程 GIL 的锁住情况,在一个“合理”的时间范围内释放 GIL
          每隔一段时间,Python 解释器就会强制当前线程去释放 GIL,这样别的线程才能有执行的机会

        • 所以check_interval机制导致随时打断程序运行,有了 GIL也还要继续考虑线程安全

      • 总结:多线程也可以被调度到多个CPU上,只是由于python的GIL的存在,python的单线程和多线程同时都只能利用一颗cpu核心,对于纯cpu heavy任务场景,不涉及到io耗时环节,cpu都是充分利用的,多线程和单线程相比反倒是多了线程切换的成本,所以性能反而不如单线程。

    • Python垃圾回收机制

        • 对象的引用计数(指针数)为 0 的时候,自然它也就成为了垃圾,需要被回收
      • 循环引用问题(有两个 list 互相引用,这里极有可能引起内存泄露)

        • 引用计数为0不是垃圾回收的充要条件

          Python 使用标记清除(mark-sweep)算法和分代收集(generational)启用针对循环引用的自动垃圾回收

          • 标记清除(mark-sweep)算法

            • 相当于遍历全图,在遍历结束后,所有没有被标记的节点,我们就称之为不可达节点。但图遍历性能消耗严重,mark-sweep 使用双向链表维护了一个数据结构,并且只考虑容器类的对象,只有容器类对象才有可能产生循环引用
          • 分代收集(generational)算法‘’

            • 新生的对象更有可能被垃圾回收,而存活更久的对象也有更高的概率继续存活
      • objgraph调试内存泄漏,可视化引用关系


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK