一、GIL(全局解释器锁)
-
GIL是为了确保在多个线程运行时,同一时刻只有一个线程在cpu上运行,这样做是为了保证在对数据进行操作的时候,能够确保数据的安全。但是即使是有了GIL,数据的安全就能保证了吗,其实不然,要说明这个,就要说说GIL什么时候会释放?咱们知道,python是解释性语言,py代码在运行的之后,会将代码解码成字节码,然后再执行,当字节码到一定行数或者代码运行时间到达一定的时间片或者进行
I/O操作的时候,GIL就会释放,然后其他线程争抢这把锁,谁抢到谁就能操作,GIL不会一值锁住只让一个线程执行,这不符合多线程的设计理念。 -
如下图,计算同一个数据+100w和-100w,其结果应该是0才对,但是结果却不是,这就是因为GIL释放的时机不对才导致的。我们假设num = 0,在add函数对num += 1,此时假设num还没有被赋值给1(也就是num还是等于0)的时候,GIL释放,执行权被desc函数获得,此时num -= 1,num此时是0的,因为add函数还没有将1赋值给num(此时desc函数的num等于0),执行
num -= 1操作,结果是num = -1,此时GIL释放,执行权被add函数获得,继续上一次的赋值操作,把1赋值给num(上一次在add函数中,1还没有赋值给num),那么这样add函数的num = 1,这样就冲突了,因为一开始num是等于0的,按理说num += 1和num -= 1之后,num的结果应该是0,而此时num却等于1,所以这就是GIL释放的时机导致这样的结果,这就是数据不安全。 -
因为有了GIL这把大锁,所以在执行
计算密集型操作的时候,速度会有所降低,但是在执行I/O密集型的时候,多线程的速度就会有所提升。 -
GIL不是python的特性,python的解释器有
Cpython和Jpython,GIL在Cpython解释器才有,而在Jpython解释器中没有,所以更换解释器可以解决这个问题,但是不建议更换,因为官方推荐的就是Cpython解释器;或者在使用多线程可以使用c语言去实现(c语言我忘的一干二净) -
那么怎么确保数据的安全呢,那就要引入多线程的锁机制了,有
Lock/RLock/Condition或者队列queue/deque也可以