本文来介绍下,多线程是如何工作的,多线程就一定效率就高吗,本文可以告诉你不一定。
- 先来了解Python解释器执行代码方式
Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。对Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
在多线程环境中,Python 虚拟机按以下方式执行:
设置GIL->切换到一个线程去运行->运行-> 把线程设置为睡眠状态->解锁GIL-> 再次重复前面步骤
2. 什么是GIL
GIL(Global Interpreter Lock),中文翻译叫全局解释器锁。下面这张图可以描述GIL的工作原理。
解释下:
一个任务三个线程去处理,上面有5段执行任务,分别有不用线程去处理。开始线程1去执行,然后遇到了GIL,这个时候就锁住了线程1,交给线程2,线程1和线程2交接的时候,有一个读写时间,这个很短。接着线程2执行完了,锁住线程2,交给线程3,然后,锁住线程3,交给线程1,锁住线程1,交给线程3,大概就是这样一个过程。
3.举例来证明,多线程效率不一定高
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 1import threading
2from queue import Queue
3import copy
4import time
5
6def job(l,q):
7 res = sum(l)
8 q.put(res)
9
10def exampleFuc(l):
11 q = Queue()
12 threads = []
13 for i in range(4):
14 t = threading.Thread(target=job, args=(copy.copy(l), q))
15 t.start()
16 threads.append(t)
17
18 [t.join() for t in threads]
19 total = 0
20 for x in range(4):
21 total = total + q.get()
22
23 print(total)
24
25def normal(l):
26 total = sum(l)
27 print(total)
28
29
30if __name__ == '__main__':
31 l = list(range(1000000))
32 s_t = time.time()
33
34 normal(l*4)
35 print('普通方法执行时间是:', time.time()-s_t)
36 s_t = time.time()
37 exampleFuc(l)
38 print('多线程执行时间是:', time.time()-s_t)
39
40
1
2 1运行结果:
2
1
2
3
4
5
6
7 1============= RESTART: C:\Users\Anthony\Desktop\thread_queue.py =============
21999998000000
3普通方法执行时间是: 0.26999735832214355
41999998000000
5多线程执行时间是: 0.3099970817565918
6>>>
7
1
2 1从结果可以看到,普通方法执行时间大概是0.2秒,多线程执行的时候是0.3秒,多线程效率反而更低。
2