1.全局解释器锁
1.1python解释器:
-Cpython c语言
-Jpython java
1.2GIL :全局解释器
-翻译:在同一个进程下开启的多线程,同一时刻只能有有一个线程执行,因为cpython的内存管理不是线程安全。
-GIL全局解释器,本质上是一把互斥锁,保证数据安全
在Cpython解释器中,同一个进程下开启多个线程,同一时刻只能有一个线程执行,无法利用多核优势。
-为什么要有全局解释器锁:
-没有锁
-GIL全局解释器锁的优点:
-优点:
保证数据的安全
-缺点:
单个进程下,开启多个线程,牺牲执行效率了,无法实现并行,只能实现并发。
-IO密集型: 多线程
-计算机密集型:多进程
import time
from threading import Thread
n = 100
def task():
global n
m = n
time.sleep(3)
n =m -1####实际产生了10个99 最后一个只打印了一个n
#print(n)
if __name__ == '__main__':
list = []
for line in range(10):
t = Thread(target = task)
t.start()
list.append(t)
for t in list:
t.join()
print(n)
>>>>>>>>>>>>>>>>>>>>>>
99
2.协程
-定义:
-进程:资源单位
-线程:执行单位
-协程:单线程西实现并发
-在IO密集的情况下,使用协程能提高最高效率
注意:协程不是任何单位,使用协程能提高最高效率
协程的目的:
-手动实现“遇到IO切换+保存状态” ,因为是在单线程下,控制单线程的多个任务在一个任务遇到io,就切换到另外一个任务执行,这样保证了,线程能够最大限度的处于就绪化,即随时都可以被cpu执行的状态,可以去欺骗操作系统,让操作系统误以为没有io操作,从而将cpu的执行权限交给你。
-必须只有单线程实现并发,
-协程指的是单个线程,一旦线程出现阻塞,及那个会阻塞整个线程
from gevent import monkey # 猴子补丁
monkey.patch_all() # 监听所有的任务是否有IO操作
#上面的2个必须写在文件的开头,在time socket的模块之前,这样形成的io 可以直接识别
from gevent import spawn # spawn(任务) spawn(函数名,参数,参数)
from gevent import joinall
import time
def task1():
print('start from task1...')
time.sleep(1)
print('end from task1...')
def task2():
print('start from task2...')
time.sleep(3)
print('end from task2...')
def task3():
print('start from task3...')
time.sleep(5)
print('end from task3...')
if __name__ == '__main__':
start_time = time.time()
sp1 = spawn(task1)
sp2 = spawn(task2)
sp3 = spawn(task3)
# sp1.start()
# sp2.start()
# sp3.start()
# sp1.join()
# sp2.join()
# sp3.join()
joinall([sp1, sp2, sp3])
end_time = time.time()
print(f'消耗时间: {end_time - start_time}')
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start task1...
start task2...
start task3...
end task1...
end task2...
end task3...
消耗时间:3.0044186115264893
3.使用多线程提高效率
from threading import Thread
from multiprocessing import Process
import time
#计算密集型任务
def task1():
i = 10
for line in range(1000000):
i += 1
#io密集型任务
def task2():
time.sleep(3)
if __name__ == '__main__':
#测试多进程
#计算密集型
a = time.time()
list1 = []
for line in range(6):
p = Process(target = task1)
print(p)
p.start()
list1.append(p)
for p in list1:
p.join()
b = time.time()
print(f'计算进程密集型消耗的时间:{b-a}')
#测试IO密集型
a = time.time()
list2 = []
for line in range(6):
p = Process(target = task2)
p.start()
list2.append(p)
for p in list2:
p.join()
b = time.time()
print(f'IO进程密集型消耗时间:{b-a}')
#2.测试多线程的
#测试计算密集型
a = time.time()
list1 = []
for line in range(6):
p = Thread(target = task1)
p.start()
list1.append(p)
for p in list1:
p.join()
b = time.time()
print(f'计算线程密集型消耗时间:{b -a}')
#测试IO密集型
a = time.time()
list1 = []
for line in range(6):
p = Thread(target = task2)
p.start()
list1.append(p)
for p in list1:
p.join()
b = time.time()
print(f'IO线程密集型的消耗时间:{b - a}')
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
计算进程密集型消耗的时间:0.3511178493499756
IO进程密集型消耗时间:3.215735912322998
计算线程密集型消耗时间:0.43486547470092773
IO线程密集型的消耗时间:3.003101110458374