Python中的GIL(全局解释器锁)与互斥锁

什么是GIL?

-GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。仅仅是因为在CPython解释器,难以移除GIL。
-当初操作系统还没有线程的概念,GIL锁对单线程来说带来了性能的提升。GIL是cpython开发者早期面对困难的一种解决方案。

线程释放GIL锁的情况

在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100

为什么GIL锁还没有删除

删除GIL会使得Python 3在处理单线程任务方面比Python 2慢,可以想像会产生什么结果。你不能否认GIL带来的单线程性能优势,这也就是为什么Python 3中仍然还有GIL。

####如何处理Python中的GIL
1.用多进程代替多线程。每一个Python进程都有自己的Python解释器和内存空间,因此GIL不会成为问题。
2.替换Python解释器
用C,Java,C#和Python编写的CPython,JPython,IronPython和PyPy是最受欢迎的,GIL只存在CPython中。

结论:
1. 在 处理像科学计算 这类需要持续使用cpu的任务的时候 单线程会比多线程快
2. 在 处理像IO操作等可能引起阻塞的这类任务的时候 多线程会比单线程快

互斥锁

当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制,
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
互斥锁为资源引入一个状态:锁定/非锁定
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;
直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:

# 创建锁
mutex = threading.Lock()

# 锁定
mutex.acquire()

# 释放
mutex.release()

注意:
如果这个锁之前是没有上锁的,那么acquire不会堵塞
如果在调用acquire对这个锁上锁之前 它已经被 其他线程上了锁,那么此时acquire会堵塞,
直到这个锁被解锁为止

上锁解锁过程
当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。

每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“阻塞”,直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。

线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

总结
锁的好处:

确保了某段关键代码只能由一个线程从头到尾完整地执行
锁的坏处:

阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁。

你可能感兴趣的:(Python编程)