一 Python GIL(Global Interpreter Lock) 全局解释器锁

如果一个主机是单核,此时同时启动10个线程,由于CPU执行了上下文的切换,让我们宏观上看上去它们是并行的,但实际上在微观上它们永远是串行的。如果一个主机有四核,代表它可以真真正正同时执行4个任务,而不是假象。但是在Python中,无论你有多少核,它永远都是假象,实际上它永远同一时间只能执行一个线程。这是Python在开发之初的一个设计缺陷。因为Python是1989年就诞生了,当时主机只有一个核,它的创始人没有考虑多核的问题。

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

上面的核心意思就是,无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行。

首先需要明确的一点是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。

这篇文章透彻的剖析了GIL对python多线程的影响,强烈推荐看一下:http://www.dabeaz.com/python/UnderstandingGIL.pdf 

二 线程锁之Lock\Rlock\信号量

 线程锁(互斥锁Mutex)

一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?

 1 import threading
 2 import time
 3 
 4 def run(n):
 5     global num #在每个线程中都获取这个全局变量
 6     num+=1 #对此公共变量进行+1操作
 7     time.sleep(2)
 8 
 9 num = 0  #设定一个共享变量
10 t_objs = []
11 
12 for i in range(100):
13     t = threading.Thread(target=run,args=("t%s" %i,))
14     t.start()
15     t_objs.append(t)
16 
17 for t in t_objs:  #等待所有线程执行完毕
18     t.join()
19 
20 print("num:",num)
View Code

相关文章: