python和c混合编程 gil_终于搞明白python与gil

感想:东看一篇文章西看一篇文章,终于把gil的概念理顺了

我们都知道,比方我有一个4核的CPU,那么这样一来,在单位时间内每个核只能跑一个线程,然后时间片轮转切换。但是Python不一样,它不管你有几个核,单位时间多个核只能跑一个线程,然后时间片轮转。看起来很不可思议?但是这就是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器

gil:全局解释器锁

存在原因:

早期设计python解释器时是单核时代,并没有考虑多核cpu情况

1.python的是使用引用计数的,当变量的引用计数为0就会被垃圾回收机制回收

2.python是解释型语言,默认的解析器cpython是将python语言翻译成c,再调用c函数实现执行python程序

3.线程与进程不同,是共享用户地址空间的,也就是共享全局变量

综上,如果同一个时刻有两个线程执行,那么全局变量的引用计数可能同时从0变成1,最终它的引用计数就是1,而却有两个线程在使用它,这显然是不对的.

解释:

全局:针对全局资源/同一个时刻,不管有多少个核,都只有一个线程能使用cpu资源

解释锁:cpython锁(C语言实现的Python解释器)

为什么java没有gil锁呢?

java实现了颗粒度更小的锁,而程序的执行顺序是:获取锁-执行程序-释放锁,所以增加了获取和释放锁的资源开销,所以全局锁这一把大锁其实也有好处,切换线程的资源浪费较少.

解释器怎么切换线程?

如果是纯计算的程序,没有 I/O 操作,解释器会每隔100次操作就释放这把锁,让别的线程有机会 执行(这个次数可以通sys.setcheckinterval来调整)同一时间只会有一个获得GIL线程在跑,其他线程都处于等待状态

哪种任务适合用多线程?

1、如果是CPU密集型代码(循环、计算等),由于计算工作量多和大,计算很快就会达到100,然后触发GIL的释放与在竞争,多个线程来回切换损耗资源,所以在多线程遇到CPU密集型代码时,单线程会比较快

2、如果是I\O密集型代码(文件处理、网络爬虫),开启多线程实际上是并发(不是并行),IO操作会进行IO等待,线程A等待时,自动切换到线程B,这样就提升了效率

怎么优化?

1.改用多进程,多个Python进程有各自独立的GIL锁

2.将计算代码转成c代码,使用调用c代码的接口,将cpu密集型任务切换成io任务:对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。我们可以把一些 计算密集型任务用C语言编写,然后把.so链接库内容加载到Python中,因为执行C代码,GIL锁会释放

与多进程使用变量的区别:

多进程:linux系统里面,fork出来的进程,其变量与源进程相同,如果只做读取,那么不会内存分配,如果发生写入,那么创建新内存页

缺点?

导致python无法实现真正意义上的多线程

Java吧 收集整理 java论坛 www.java8.com

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值