Python线程——你必须知道的东西!

在介绍Python中的线程之前,先明确一个问题,Python中的线程是假的多线程!,为什么这么说,我们先明确一个概念,全局解释器锁GIL。

python代码是由Python虚拟机(解释器)来控制。Python在设计之初就要考虑在主循环中,同时只有一个线程在执行,就像单cup的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻只有一个程序在cpu中运行,同样的,虽然Python解释器可以运行多个线程,只有一个线程在解释器运行。

对Python虚拟机的访问由全局解释器锁GIL来控制,正是这个锁能保证同时只有一个线程在运行。在多个线程环境中,Python虚拟机按照以下方式执行。

1.设置GIL。

2.切换到一个线程去执行。

3.运行。

4.把线程设置为睡眠状态

5.解锁GIL

6.再次重复以上的步骤。

对所有面向I/O的(会调用内建的操作系统c代码的)程序来说,GIL会在这个I/O调用之前释放,以允许其他线程在这个线程等待I/O的时候运行。如果某线程并未使用很多的I/O操作,它会在时间片内一直占用处理器和GIL,也就是说,I/O密集型的Python程序比计算密集型的Python程序更能充分利用多线程的好处。

我们知道,比如我有一个4核的cpu,那么这样,在单位时间内每个核都能跑一个线程,然后时间片切换。但是Python不一样,它不管几个核,单位时间多个核只能跑一个线程,

然后时间片轮换,都是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后执行100条字节码解释器就会自动释放锁,让别的线程有机会执行。这个GIL实际上都是把所有线程执行代码都是上了锁,所以,多线程Python只能交替执行,即使100个线程跑在100个核上面,也只能用到一个核。

做个实验:


#coding=utf-8

from multiprocessing import Pool

from threading import Thread

from multiprocessing import Process

def loop():

            while True:

                    pass

if __name__=='__main__'

    for i in range(3):

            t = Thread(target=loop)

            t.start()

            while True:

                pass

电脑是4核,开了4个线程,看一下cpu资源占有率:


我们发现cpu利用率并没有占满,相当于单核水平

而如果我们改变进程:



#coding=utf-8

from multiprocessing import Pool

from threading import Thread

from multiprocessing import Process

def loop():

            while True:

                    pass

if __name__=='__main__'

    for i in range(3):

            t = Process(target=loop)

            t.start()

            while True:

                pass


结果很高,说明,进程是可以利用多核的!

验证GIL搞的鬼,尝试用java写相同的代码:



由此可见java的多线程是可以利用多核的,这是真正的多线程,而Python中的多线程只能利用单核,这是假的多线程

我们没有办法在Python中利用多核?可以!刚才的多进程是一种方式,还有一种就是调用c语言的连接库。对所有面向I/O的(会调用内建操作系统c代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。我们可以把计算密集型的任务用C 语言编写,然后.so链接库内容加载到Python中,因为执行c代码,GIL会释放锁,这样一来就可以做到每个核都跑一个线程的目的

总之,I/O密集型代码适合简单的脚本语言,计算密集型的语言适合c语言








#coding=utf-8

from multiprocessing import Pool

from threading import Thread

from multiprocessing import Process

def loop():

            while True:

                    pass

if __name__=='__main__'

    for i in range(3):

            t = Thread(target=loop)

            t.start()

            while True:

                pass

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值