• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

GIL全局解释器锁

python 搞java代码 3年前 (2022-05-21) 13次浏览 已收录 0个评论

GIL全局解释器锁

1、什么是GIL全局解释器锁

  GIL:Global Interpreter Lock,意思就是全局解释器锁,这个GIL并不是Python的特性,他是只在Cpython解释器里引入的一个概念,而在其他的语言编写的解释器里就没有GIL,例如:Jython,Pypy等

 

  下面是官方给出的解释:

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.)

  翻译过来的意思就是:在CPython中,全局解释器锁(GIL)是一个互斥锁,可以防止多个本地线程同时执行Python字节码。这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。(但是,由于GIL存在,其他特性已经发展到依赖于它所执行的保证。)

  所以:

    GIL本质上就是一把互斥锁用来保证数据的正确性使数据可以正常同步

    GIL就像是BUG一般存在的全局互斥锁,目前无法通过代码去除GIL

 

  结论:在CPython解释器中,在同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

  PS:我们平常所使用的python是C语言编写的,所以大部分人所说的python也指CPython,CPython是python的官方版本,若是指其他语言写的python,一般情况下会指明,如Jypthon、Pypy等

 

 

2、为什么会出现GIL

  随着电脑多核CPU的出现,python为了充分利用多核CPU,进行多线程的编程方式便普及了起来,但是随之而来的困难是线程之间数据的一致性和状态同步,python为了解决这个数据不能同步的问题,所以设计了GIL全局解释器锁,其实就是互斥锁

  说到互斥锁,在多线程互斥锁中共享全局变量的时候会有线程对全局变量进行的资源竞争,会对全局变量的修改产生不是我们想要的结果,而那个时候用到的是python中线程模块里面的互斥锁。

  如下例(未加线程互斥锁):

<span>from</span> threading <span>import</span><span> Thread</span><span>import</span><span> time


n </span>= 100
<span>def</span><span> task():
    </span><span>global</span><span> n
    m </span>=<span> n
    time.sleep(</span>0.5)    <span>#</span><span> 模拟IO操作</span>
    n = m - 1


<span>if</span> <span>__name__</span> == <span>"</span><span>__main__</span><span>"</span><span>:
    list1 </span>=<span> []
    </span><span>for</span> i <span>in</span> range(10<span>):
        t </span>= Thread(target=<span>task)
        t.start()
        list1.append(t)

    </span><span>for</span> t <span>in</span><span> list1:
        t.join()

    </span><span>print</span>(n)
www#gaodaima.com来源gaodai^.ma#com搞#代!码网搞代码

  执行结果:

99

  在上面的例子里,我创建了10个线程来争夺对 n 进行 -1 操作,但是结果并非我想要的,所以我在这里加入了互斥锁

  如下例(加线程互斥锁):

<span>from</span> threading <span>import</span><span> Thread
</span><span>from</span> threading <span>import</span><span> Lock
</span><span>import</span><span> time


n </span>= 100
<span>def</span><span> task(lock):
    </span><span>global</span><span> n
    lock.acquire()    </span><span>#</span><span> 加锁</span>
    m =<span> n
    time.sleep(</span>0.5)    <span>#</span><span> 模拟IO操作</span>
    n = m - 1<span>
    lock.release()    </span><span>#</span><span> 解锁</span>


<span>if</span> <span>__name__</span> == <span>"</span><span>__main__</span><span>"</span><span>:
    list1 </span>=<span> []
    lock </span>=<span> Lock()
    </span><span>for</span> i <span>in</span> range(10<span>):
        t </span>= Thread(target=task, args=<span>(lock, ))
        t.start()
        list1.append(t)

    </span><span>for</span> t <span>in</span><span> list1:
        t.join()

    </span><span>print</span>(n)

  执行结果:

90

  这次就可以得到我想要的结果,在前面我的进程和线程的博文里也说到过这个问题。

 

 

3、GIL的优缺点

  优点:

    保证数据的正确性

  缺点:

    单个进程下,开启多个线程,牺牲了执行效率,无法实现并行,只能实现并发

 

 

4、如何体现GIL全局解释器锁

  在Cpython解释器中,当python代码有一个线程开始访问解释器的时候,GIL会把这个大锁给锁上,此时此刻其他的线程只能干等着,无法对解释器的资源进行访问,这一点就和互斥锁相似。而只是这个过程发生在我们的Cpython中,同时也需要等这个线程分配的时间到了,这个线程把GIL释放掉,类似互斥锁的lock.release()一样,另外其他的线程才开始跑起来。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:GIL全局解释器锁

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址