文字内容
1. gil那些事⼉ 峰云就她了 http://xiaorui.cc
2. 相关 什么是python解释器 CPython vs pypy vs Jython
3. gil 什么是 Global Interpreter Lock Python为什么会有gil gil的优缺点 关于gil的历史
4. O -1 Thread A 1. 2. 3. 4. Thread B get the current length check if there’s room for more Append element Incrment the length by 1
5. Python’ s 线程 python线程是系统线程的. POSIX threads (pthreads) Windows threads 受内核来调度并切换上下⽂
6. 性能对比 thread only def go_count(n): while n > 0: n -= 1 COUNT = 100000000 # 100 million go_count(COUNT) cost 10s thread two t1 = Thread(target=go_count,args=(COUNT//2,)) t2 = Thread(target=go_count,args=(COUNT//2,)) t1.start(); t2.start() t1.join(); t2.join() cost 21s
7. 那么问题来了 多线程为什么比单线程还慢 ? python解释器运⾏原理 只有⼀个线程在running 多线程acquire lock的消耗成本
8. gil 简单描述: 拿到gil锁,谁就可以running , 当释放gil, send signal 没拿到gil锁, 休眠. 内核调度到你, 你如果没锁, sleep and wait for a signal 什么时候释放锁: IO Block every 100 tick force, default gil 是mutex + semaphore + condition
9. _mysql.c gil process check_connection(self); Py_BEGIN_ALLOW_THREADS r = mysql_real_query(&(self->connection), query, len); Py_END_ALLOW_THREADS
10. scheduler I/O run I/O release acquire run I/O release run I/O run release release acquire acquire I/O acquire
11. scheduler counter c run 100 ticks h run 100 ticks c h run 100 ticks c h e e e c c c k k k acquire acquire release release release acquire Change it using sys.setcheckinterval()
12. what a check Periodic “check” is simple The currently running thread … reset the tick counter run signal handler if this is main thread relase the gil Reacquires the gil
13. A tick ? def go(): a = True for i in range(3): print i if a: print "xiaorui.cc" b = None c = 123
14. wake up Condition Variable enqueue 等待wake up的线程队列 thread 7 thread 3 thread 5 thread 2 signal dequeue thread 1
15. t2 t2 t2 t2 t2 t2 t1 t2 t2 t1 t1 t1 t2 t1 t1 t1 t2 t1 t2 t1 t1 t2 100 5351 ENTRY 100 5351 ACQUIRE 100 5352 RELEASE 100 5352 ENTRY 100 5352 ACQUIRE 100 5353 RELEASE 100 5353 ACQUIRE 100 5353 ENTRY 38 5353 BUSY 100 5354 RELEASE 100 5354 ENTRY 100 5354 ACQUIRE 79 5354 RETRY 100 5355 RELEASE 100 5355 ENTRY 100 5355 ACQUIRE 73 5355 RETRY 100 5356 RELEASE 100 5356 ACQUIRE 100 5356 ENTRY 24 5356 BUSY 100 5357 RELEASE 进⼊临界区 获取锁 释放锁 没拿到锁 重新尝试
16. break to think python如何保证list\dict的操作原⼦性 某个线程⼀直⾼比率拿到锁 ? t1时间片用完了, kernel把t2调度起来, 但gil还在t1⼿里 ? 多线程都在⼀个cpu core上 ?
17. 不公平竞争 check T1 check 100 tciks 100 tciks release … suspended signal wake os signal T2 … suspended thread cs 100 tciks
18. 不公平竞争 Thread A (cpu 1) release gil Thread B (cpu 2) signale acquire gil acquire gil (fail) 多核 release gil acquire gil waked signale waked acquire gil (fail)
19. new gil check 100 tciks 100 tciks T1 cv_wait(gil,TIMEOUT) suspended signale gil_drop_request = 1 suspended T2 cv_wait(gil,TIMEOUT) timeout gil_drop_request = 0 100 tciks
20. 那么threading场景 由于有gil全局锁, python多线程的意义 ? IO 密集 CPU 密集 python的线程调度策略 再次声明,解释器没有thread调度器
21. 特例, Signal 当信号到达的时,解释器会按照每个tick都要check. 直到main thread处 理了signal.
22. 绕过gil multiprocessing python gil 存在于线程之间 ctypes 调用c函数之前, 会释放gil more … …
23. kill gil python能否去掉gil ? 如何实现python底层去gil ? 去掉之后又会出现什么 ? 总结: 值不值, 成本 ?
24. “Q & A” –峰云就她了