一篇文章彻底搞明白GIL

注: 本章测试代码在双核cpu的ubuntu系统下

单线程执行死循环

while True:
	pass

执行上面代码,单线程死循环已经占满了一个cpu核
在这里插入图片描述
然后上面代码再次运行一份。 相当于同时运行2个 线程死循环 程序,我们看到俩个核全部被占满
在这里插入图片描述

多线程执行死循环

import threading

# 子线程死循环
def test():
	while True:
		pass
		
t1 = threading.Thread(target=test)
t1.start()

# 主线程死循环
while True:
	pass

执行上面的代码,我们看到俩个核加起来的资源占有率是的一个的核的资源在这里插入图片描述
由此,我们得出结论:
我们的多线程程序实际上是假的多任务

多进程执行死循环

import multiprocessing

# 子进程死循环
def test():
	while True:
		pass
		
t1 = multiprocessing.Process(target=test)
t1.start()

# 主进程死循环
while True:
	pass

执行上面代码,我们看到俩个核都被占满
在这里插入图片描述

结论

当我们完成一项任务,使用了多线程,多进程。真正起到作用的是多进程,多线程其实是假的

GIL(全局解释器)

为什么线程是假的?
因为每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。

Python语言运行需要解释器,通常我们用的,官网推荐的 是Cpython虚拟机解释器,由于历史也原因,难以移除。Cpython的作者曾经尝试去移除GIL,但是最终的效果没有GIL快,所以发布声明,同时也建议,如果你要发挥多核cpu的能力,就使用进程

那么问题来了:
编写一个多线程的爬虫程序,是否比单线程的要快?
答案是肯定的 多线程的爬虫程序比单线程的要快

这里要说说计算密集型程序 和 IO密集型程序

  1. 计算密集型: 直白点就是程序没有延时操作
  2. IO密集型: 程序执行中有读写操作,比较耗时

因为网络请求、文件读取等操作 就是典型的IO密集型操作 是耗时的,GIL可以充分利用这些空闲时间。所以多线程在比单线程快。
所以:

  1. 计算密集型: 用进程
  2. IO密集型: 用线程、携程

怎样克服GIL的问题

换掉Cpython解释器,用其他解释器
  • PyPy
    PyPy是另一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。

    绝大部分Python代码都可以在PyPy下运行,但是PyPy和CPython有一些是不同的,这就导致相同的Python代码在两种解释器下执行可能会有不同的结果。如果你的代码要放到PyPy下执行,就需要了解PyPy和CPython的不同点。

  • Jython
    Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。

  • IronPython
    IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。

使用其它的语言(c/c++、java、javascript等)实现多线程代码,然后使用python去调用

python是胶水语言,可以很方便的调用其他语言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值