• Python中的全局解释器锁
  • 发布于 2个月前
  • 208 热度
    0 评论
  • 林顺忍
  • 3 粉丝 42 篇博客
  •   
首先我们要搞清楚的一些概念。
程序:程序员开发的代码,还没有运行,保存在磁盘中的。

进程:运行中的程序,需要耗费电脑的cpu,内存等资源。

线程:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

如果把程序比喻成一个酒店,那么进程就是包房。(包房里面有空调,厕所,桌子等)。
线程就是包房里面的一套桌子。

线程和进程的关系以及区别?


进程和线程的关系:

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。(这个好理解,一个桌子肯定属于某个包房,一个包房可以有多张桌子,最少有一张)

(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。(资源按照包房分,同一个包房的共享空调,厕所等)

(3)处理机分给线程,即真正在处理机上运行的是线程(真正用来吃饭的是桌子)

(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.

进程与线程的区别:

(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
(这个好理解,桌子是最吃饭基本的分配单位,包房是资源的基本单位)
进程不能单独执行,它只是资源的集合。
进程要操作CPU,必须要先创建一个线程。
所有在同一个进程里的线程,是同享同一块进程所占的内存空间。

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行。(好理解,不同包房可以同时开饭,同一个包房不同桌也可以同时开饭。)

(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.(你定了包房,就定了里面的资源和服务,要多算钱的,每桌客人都可以公用包房里的东西)

(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。(一个包房的开销,肯定比一个桌的开销大)

并行:多个CPU同时执行多个任务,就好像有两个程序,这两个程序是真的在两个不同的CPU内同时被执行。(比如有两个服务员,同时服务两个包房)

并发:CPU交替处理多个任务,还是有两个程序,但是只有一个CPU,会交替处理这两个程序,而不是同时执行,只不过因为CPU执行的速度过快,而会使得人们感到是在“同时”执行,执行的先后取决于各个程序对于时间片资源的争夺

并发其实是串行。(如同有一个服务员,同时服务一个包房的两桌,由于速度快,两桌看起来似乎同时开饭。实际上有先后,只是时间太短,看不出来)

GIL (Global Intercepto Lock)全局解释器锁
首先需要明确的一点是 GIL 并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。
并行和并发同属于多任务,目的是要提高CPU的使用效率。这里需要注意的是,一个CPU永远不可能实现并行,即一个CPU不能同时运行多个程序,但是可以在随机分配的时间片内交替执行(并发),就好像一个人不能同时看两本书,但是却能够先看第一本书半分钟,再看第二本书半分钟,这样来回切换。

Guido van Rossum(吉多·范罗苏姆)创建python时就只考虑到单核cpu,解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁, 于是有了GIL这把超级大锁。因为cpython解析只允许拥有GIL全局解析器锁才能运行程序,这样就保证了保证同一个时刻只允许一个线程可以使用cpu。由于大量的程序开发者接收了这套机制,现在代码量越来越多,已经不容易通过c代码去解决这个问题。

每个线程在执行时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说多线程并不是真正意义上的同时执行。

多线程如同客人要用包房里的厕所,一次只能一个人用。进去的人把门锁住。用完释放,下一个人接着用。

进程如同独立包房,一个厕所够了,不需要排队,也就不需要锁了。

那么,我们改如何解决GIL锁的问题呢?

1.更换cpython为jpython(不建议)
2.使用多进程完成多线程的任务
3.在使用多线程可以使用c语言去实现

以下是几个面试会遇到的问题,希望对大家有所帮助:

问题1: 什么时候会释放Gil锁,
答 :
1 遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil
2 会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:
ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)

问题2: 互斥锁和Gil锁的关系

Gil锁 : 保证同一时刻只有一个线程能使用到cpu
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱

GIL与多线程
有了GIL的存在,python有这两个特点:
1、进程可以利用多核,但是开销大。
2、多线程开销小,却无法利用多核优势。
也就是说Python中的多线程是假的多线程,Python解释器虽然可以开启多个线程,但同一时间只有一个线程能在解释器中执行,而做到这一点正是由于GIL锁的存在,它的存在使得CPU的资源同一时间只会给一个线程使用,而由于开启线程的开销小,所以多线程才能有一片用武之地,不然就真的是鸡肋了。

而python的多线程到底有没有用,我们需要看任务是I/O密集型,还是计算密集型:如果是I/O密集型任务,有再多核也没用,即能开再多进程也没用,所以我们利用python的多线程一点问题也没有;如果是计算密集型任务,我们就直接使用多进程就可以了。

用户评论