GIL全称Global Interpreter Lock
一、都说GIL锁,那么他具体是什么呢
1. GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC, INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的 Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL
2. 那么CPython实现中的GIL又是什么呢?GIL全称Global Interpreter Lock为了避免误导,我们还是来看一下官方给出的解释:
二、为什么会有GIL
Python为了利用多核,Python开始支持多线程。而解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁。 于是有了GIL这把超级大锁,而当越来越多的代码库开发者接受了这种设定后,他们开始大量依赖这种特性(即默认python内部对象是thread-safe的,无需在实现时考虑额外的内存锁和同步操作)。
三、GIL的影响
甚至就几乎等于Python是个单线程的程序。
GIL的存在导致多线程无法很好的立即多核CPU的并发处理能力。
Python的多线程在多核CPU上,只对于IO密集型计算产生正面效果;而当有至少有一个CPU密集型线程存在,那么多线程效率会由于GIL而大幅下降。
四、那么什么时候用线程什么时候用进程呢
1.计算密集型时用进程
2.IO密集型时用线程
3.当然一个程序中肯定会有IO,只是相对来说
线程的应用场景
from threading import Thread,Lock
import time
n=100
def task():
global n
mutext.acquire()
temp=n
time.sleep(0.1)
n=temp-1
mutext.release()
if __name__ == '__main__':
t_l=[]
mutext=Lock()
start=time.time()
for i in range(3):
t=Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
print(time.time()-start)
print(n)
进程应用场景
#计算密集型:多进程效率高
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=0
for i in range(10000000):
res*=i
if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range(4):
p=Process(target=work) #耗时run time is 0.8030457496643066
# p=Thread(target=work) #耗时run time is 2.134121894836426
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time() #
print('run time is %s' %(stop-start))
from threading import Thread
import os,time
def work():
time.sleep(2)
if __name__ == '__main__':
l=[]
start=time.time()
for i in range(100):
# p=Process(target=work) #耗时run time is 4.881279230117798
p=Thread(target=work) #耗时run time is 2.011115074157715
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time() #
print('run time is %s' %(stop-start))
五、总结
1.每一个cpython进程内都有一个GIL
2.GIL导致同一进程内的多个线程同一时间只能有一个运行
3.之所以有GIL,是因为Cpython的内存管理不是线程安全的
4.对于计算密集型用多进程,多IO密集型用多线程