美文网首页
浅谈Python的GIL机制

浅谈Python的GIL机制

作者: Python技术漫谈 | 来源:发表于2018-10-29 20:09 被阅读0次

    python多线程

    实验:

    • 开启两个线程
    • 一个线程sleep 4s 死循环打印
    • 另外一个线程sleep 1s 死循环打印

    结果:会正常的交替运行
    结论:一个线程被阻塞的时候,CPU会被释放,然后另外一个线程被执行。。

    使用python为例子

    参考资料:

    [http://zhuoqiang.me/python-thread-gil-and-ctypes.html](http://zhuoqiang.me/python-thread-gil-and-ctypes.html)
    

    所有Thread的PID都与主程序相同,而每个Process都有一个不同的PID要

    单线程

    使用如下的代码:

    #!coding=utf8
    """
    使用多核
    """
    import sys
    sys.path.append('../../')
    
    if __name__ == "__main__":
       print("start run here")
       while True:
           a = 4 / 34.0
       print('end run here')
    
    

    开始运行前


    image.png

    使用
    python expmultiprocess.py

    开始运行后


    image.png

    可以看出,占满一个核心的所有资源了。

    主线程外再开启一个线程


    image.png

    可以看出:

    1. 有两个进程号。PID是不一样的。
    2. 所有的CPU并没有占満

    因为GIL的原因:

    1. 单进程单线程可以占用并占满一个核心。
    2. 单进程多线程可以占用多核心但无法占满,只会分时复用。

    GIL全局解释器锁

    参考资料:http://zhuoqiang.me/python-thread-gil-and-ctypes.html

    GIL 的全程为 Global Interpreter Lock ,意即全局解释器锁。
    在 Python 语言的主流实现 CPython 中,GIL 是一个货真价实的全局线程锁,在解释器解释执行任何 Python 代码时,都需要先获得这把锁才行,在遇到 I/O 操作时会释放这把锁。如果是纯计算的程序,没有 I/O 操作,解释器会每隔 100 次操作就释放这把锁,让别的线程有机会执行,这个次数可以通过sys.setcheckinterval。
    所以虽然 CPython 的线程库直接封装操作系统的原生线程,但 CPython 进程做为一个整体,同一时间只会有一个获得了 GIL 的线程在跑,其它的线程都处于等待状态等着 GIL 的释放。这也就解释了我们上面的实验结果:虽然有两个死循环的线程,而且有两个物理 CPU 内核,但因为 GIL 的限制,两个线程只是做着分时切换,总的 CPU 占用率还略低于 50%。

    以java为例子

    Java的多线程是完全可以把多个核心跑满的。

    package com.data;
    
    public class ThreadDemo extends Thread {
    
    public ThreadDemo() {
    
    }
    
    public void run() {
    
    while (true) {
    
    continue;
    
    }
    
    }
    
    public static void main(String[] args) {
    
    try {
    
    ThreadDemo h1 = new ThreadDemo();
    
    h1.start();
    
    ThreadDemo h2 = new ThreadDemo();
    
    h2.start();
    
    ThreadDemo h3 = new ThreadDemo();
    
    h3.start();
    
    h1.join();
    
    h2.join();
    
    h3.join();
    
    } catch (InterruptedException e) {
    
    // TODO Auto-generated catch block
    
    e.printStackTrace();
    
    }
    
    }
    
    }
    
    

    里面开启了三个线程,然后CPU三个核心都跑满了。

    image.png

    使用pyspark运行

    Python可以通过一些专门的数据处理框架来实现高效利用CPU,直接所有的核心都利用起来了。不用自己再去写并行计算的内容结构了。

    image.png

    相关文章

      网友评论

          本文标题:浅谈Python的GIL机制

          本文链接:https://www.haomeiwen.com/subject/tpsitqtx.html