GIL全局解释器锁与协程

一、GIL全局解释器锁

在同一个进程下开启的多线程,同一时刻只能有一个线程执行,因为Cpython的内存管理不是线程安全

GIL全局解释器锁,本质上就是一把互斥锁,保证数据安全

 1 import time
 2 from threading import Thread
 3 
 4 n = 100
 5 
 6 
 7 def task():
 8     global n
 9     m = n
10     time.sleep(3)
11     n = m - 1
12 
13 
14 if __name__ == '__main__':
15     list1 = []
16     for line in range(10):
17         t = Thread(target=task)
18         t.start()
19         list1.append(t)
20 
21     for t in list1:
22         t.join()
23 
24     print(n)

在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

优点:

  保证数据的安全性

缺点:

  单个进程下,开启多个线程,牺牲执行效率,无法实现并行,只能实现并发

不同情况下使用多进程或者多线程比较

IO密集型下使用多线程.
计算密集型下使用多进程

 1 # 计算密集型任务
 2 def task1():
 3     # 计算1000000次 += 1
 4     i = 10
 5     for line in range(10000000):
 6         i += 1
 7 
 8 
 9 # IO密集型任务·
10 def task2():
11     time.sleep(3)
12 
13 
14 if __name__ == '__main__':
15     # 1、测试多进程:
16     # 测试计算密集型
17     start_time = time.time()
18     list1 = []
19     for line in range(6):
20         p = Process(target=task1)
21         p.start()
22         list1.append(p)
23     for p in list1:
24         p.join()
25     end_time = time.time()
26     # 消耗时间: 0.9640259742736816
27     print(f'计算密集型消耗时间: {end_time - start_time}')
28 
29     # 测试IO密集型
30     start_time = time.time()
31     list1 = []
32     for line in range(6):
33         p = Process(target=task2)
34         p.start()
35         list1.append(p)
36     for p in list1:
37         p.join()
38     end_time = time.time()
39     # 消耗时间: 3.1492795944213867
40     print(f'IO密集型消耗时间: {end_time - start_time}')
41 
42 
43     # 2、测试多线程:
44     # 测试计算密集型
45     start_time = time.time()
46     list1 = []
47     for line in range(6):
48         p = Thread(target=task1)
49         p.start()
50         list1.append(p)
51     for p in list1:
52         p.join()
53     end_time = time.time()
54     # 消耗时间: 3.3614895343780518
55     print(f'计算密集型消耗时间: {end_time - start_time}')
56 
57     # 测试IO密集型
58     start_time = time.time()
59     list1 = []
60     for line in range(6):
61         p = Thread(target=task2)
62         p.start()
63         list1.append(p)
64     for p in list1:
65         p.join()
66     end_time = time.time()
67     # 消耗时间: 3.002037763595581
68     print(f'IO密集型消耗时间: {end_time - start_time}')

二、协程

进程、线程、协程: 

- 进程: 资源单位
- 线程: 执行单位
- 协程: 单线程下实现并发

在IO密集型的情况下,使用协程能提高最高效率

协程作用:

  手动实现 “遇到IO切换 + 保存状态” 来欺骗操作系统,让操作系统误以为没有IO操作,将CPU的执行权限给你

 1 from gevent import monkey  # 猴子补丁
 2 monkey.patch_all()  # 监听所有的任务是否有IO操作
 3 from gevent import spawn  # spawn(任务)
 4 from gevent import joinall
 5 import time
 6 
 7 def task1():
 8     print('start from task1...')
 9     time.sleep(1)
10     print('end from task1...')
11 
12 def task2():
13     print('start from task2...')
14     time.sleep(3)
15     print('end from task2...')
16 
17 def task3():
18     print('start from task3...')
19     time.sleep(5)
20     print('end from task3...')
21 
22 
23 if __name__ == '__main__':
24 
25     start_time = time.time()
26     sp1 = spawn(task1)
27     sp2 = spawn(task2)
28     sp3 = spawn(task3)
29     # sp1.start()
30     # sp2.start()
31     # sp3.start()
32     # sp1.join()
33     # sp2.join()
34     # sp3.join()
35     joinall([sp1, sp2, sp3])
36 
37     end_time = time.time()
38 
39     print(f'消耗时间: {end_time - start_time}')

 

 

 

 

 

 

posted @ 2019-12-09 15:40  treeter  阅读(184)  评论(0编辑  收藏  举报