• 小侠龙旋风
    2019-07-06
    先mark一下学到的知识点:
    一、查看引用计数的方法:sys.getrefcount(a)
    二、CPython引进GIL的主要原因是:
    1. 设计者为了规避类似内存管理这样的复杂竞争风险问题(race condition);
    2. CPython大量使用C语言库,但大部分C语言库都不是线程安全的(线程安全会降低性能和增加复杂度)。
    三、绕过GIL的两种思路:
    1. 绕过CPython,使用JPython等别的实现;
    2. 把关键性能代码放到其他语言中实现,比如C++。


    问答老师的问题:
    1. cpu-bound属于计算密集型程序,用多线程运行时,每个线程在开始执行时都会锁住GIL、执行完会释放GIL,这两个步骤比较费时。相比单线程就没有切换线程的问题,所以更快。
    相反,在处理多阻塞高延迟的IO密集型程序时,因为多线程有check interval机制,若遇阻塞,CPython会强制当前线程让出(释放)GIL,给其他线程执行的机会。所以能提高程序的执行效率。
    2. 第二个问题摘抄了知乎上的讨论:
    在python3中,GIL不使用ticks计数,改为使用计时器(执行时间达到阈值后interval=15毫秒,当前线程释放GIL),这样对CPU密集型程序更加友好,但依然没有解决GIL导致的同一时间只能执行一个线程的问题,所以效率依然不尽如人意。多核多线程比单核多线程更差,原因是单核下多线程,每次释放GIL,唤醒的那个线程都能获取到GIL锁,所以能够无缝执行,但多核下,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低。
    经常会听到老手说:“python下想要充分利用多核CPU,就用多进程”,原因是什么呢?原因是:每个进程有各自独立的GIL,互不干扰,这样就可以真正意义上的并行执行,所以在python中,多进程的执行效率优于多线程(仅仅针对多核CPU而言)。所以我们能够得出结论:多核下,想做并行提升效率,比较通用的方法是使用多进程,能够有效提高执行效率。
    展开
     2
     52
  • leixin
    2019-07-01
    老师,我曾经去某大厂面试。人家问了我几个问题,比说说,你知道元类吗?Python是如何解决循环引用的?换句话说,Python的垃圾回收机制是如何?我后来自己找了些资料看了,还是,不是理解的特别明白。老师后面的课程能帮我们讲解下吗?
    
     21
  • leixin
    2019-07-01
    有重要的一点没讲,GIL会在遇到io的时候自动释放,给其他线程执行的机会,这样Python多线程在io阻塞的多任务中有效。
    
     12
  • SCAR
    2019-07-01
    1.cpu-bound任务的多线程相比单线程,时间的增加在于锁添加的获取和释放的开销结果。
    2.返回到python诞生的年代,GIL相对来说是合理而且有效率的,它易于实现,很容易就添加到python中,而且它为单线程程序提供了性能提升。以至于Guido在“It isn't Easy to Remove the GIL”里面说“ I'd welcome a set of patches into Py3k only if the performance for a single-threaded program (and for a multi-threaded but I/O-bound program) does not decrease”。而到现在为止,任何尝试都没有达到这一条件。

     1
     5
  • helloworld
    2019-07-01
    python的单线程和多线程同时都只能利用一颗cpu核心,对于纯cpu heavy任务场景,不涉及到io耗时环节,cpu都是充分利用的,多线程和单线程相比反倒是多了线程切换的成本,所以性能反而不如单线程。
    
     4
  • 程序员人生
    2019-07-01
    t1 = Thread(target=CountDown, args=[n // 2]) 老师,这段代码里面n//2是什么意思?
     6
     2
  • farFlight
    2019-07-01
    另外,在测试不加锁的 foo 函数的时候,我这里循环测试10000次也不会见到n!=100的情况,这是为什么呢?
     1
     2
  • 苹果
    2020-02-04
    自己的比喻理解
    1,单线程,有语文(1),数学(2),英语(3)作业,按照顺序123写问作业
    2,多线程,在Cpython解释器种,有GIL存在,按照check interval 机制,是语文作业写5分钟,换着数学作业写5分钟,英语5分钟,在换着语文写:线程阻塞的情况,理解为数学有道题目很难,(I/O密集)提前不做,释放出来,
    3,多进程,找两个人帮忙做,三个人分别做语文,数学,英语,最后完成的算终止时间,
    线程安全理解为,做语文作业时,不需要用到数学作业里的资料,工具,
    展开
    
    
  • jackstraw
    2020-01-15
    关于绕过GIL的第二个方式:将关键的性能代码放到别的语言中(通常C++)实现;这种解决方式指的是在别的语言中使用多线程的方式处理任务么?就是不用python的多线程,而是在别的语言中使用多线程?

    作者回复: 对

    
    
  • Paul Shan
    2019-11-21
    GIL在Python作为脚本或者客户端程序没问题,作为高性能程序多少有点问题。当引入协程后,并发被很好处理,现在只剩下并行不太理想,用的是多进程模型,没有利用操作系统最小调度单元。
    
    
  • Paul Shan
    2019-11-21
    Python 多线程是伪多线程。
    
    
  • 建强
    2019-10-25
    思考题1:
    由于GIL采用轮流运行线程的机制,GIL需要在线程之间不断轮流进行切换,线程如果较多或运行时间较长,切换带来的性能损失可能会超过单线程。

    思考题2:
    个人觉得GIL仍然是一种好的设计,虽然损失了一些性能,但在保证资源不发生冲突,预防死锁方面还是有一定作用的。

    以上是个人的一点肤浅理解,请老师指正。
    展开

    作者回复: 讲的不错

    
    
  • 自由民
    2019-10-15
    思考题
    1.线程切换有开销成本,另外最主要是由于GIL的存在使python的并行为伪并行。
    2.我觉得不是好设计,像戴着镣铐跳舞,好处仅仅是简化了解释器的设计。而且它并不能完全解决线程安全问题。但我平时很少用多线程编程,所以还没有实际体会。而像解释器这样的基础设施应该是把脏活留给自己,尽量减少用户的复杂性。类似还有从python2到python3的大变动。
    
    
  • 扶幽
    2019-10-13
    第一问:因为Python中有GIL的存在,使得在每一个时刻都只能有一个线程在运行。如果强行使用多线程的话,线程的切换回耗费额外的资源,所有运行更慢;
    第二问:有,使用Python编写的有限元数值程序运算很慢,而且当时也不懂什么线程安不安全,也不会加锁,最后算出来的结果怎么都跟标准答案对不上。
    :-P
    
    
  • Geek_54edc1
    2019-09-24
    1、线程切换对性能有消耗 2、GIL的设计方便了CPython的编写,但是对使用者不太友好
    
    
  • Hector
    2019-09-19
    我有个问题,多核cpu下的多线程比单核cpu下的多线程(假设一个进程)的效率是更低的,原因是线程颠簸。老师能解释下线程颠簸么?多核cpu下的多线程GIL是怎么释放的,其他线程是怎么争夺的?
    
    
  • Nick
    2019-08-10
    老师,想请教一下:文中在“Python 的线程安全”的一节中,以foo函数的字节码为例,说“这四行 bytecode 中间都是有可能被打断的”。我觉得,即使比如在某行bytecode执行完之后线程被打断了,等这个线程重新获得GIL后不是会继续接着执行后面的bytecode吗,因此从结果看,最终每一条bytecode都被执行完了,那么对结果应该是不会有影响的呀?
     1
    
  • taoist
    2019-07-25
    1. 线程切换需要成本(CPU资源) ,CPU密集场合使用多线程会更慢
    2. 刚开始是一个好设计,可以更快更简洁更高效的实现代码,后来就成了历史的遗留的包袱,有大量的库依赖GIL 带来的线程安全,废除的成本非常高,因此CPython 只能不断改进 GIL,很难一次性彻底取消。
    
    
  • 且听疯吟
    2019-07-17
    1. pyhton的多线程按照文中所说的实际上还是单线程的实现,表面上使用了python的多线程,但实际还是单线运行,相比较单线程而言还多了许多进程切换的锁的开销,因此多线程版本反而比单线程版本要慢。
    
    
  • 贺宇
    2019-07-15
    和ruby一样
    
    
我们在线,来聊聊吧