GIL全局解释器锁

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

GIL本质是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL同一进程内的多线程,必须抢到GIL之后才能使用Cpython解释器来执行自己的代码,即同一进程下的多个线程无法实现并行,但可以实现并发

Cpython解释器下想实现并行可以开启多个进程

2、为何要有GIL

因为Cpython解释器的垃圾回收机制不是线程安全的,保证了数据的安全

3、GIL全局解释器的优缺点

优点:保证了数据安全

缺点:单个进程下开启多个线程只能实现并发不能实现并行

4、选择多进程还是多线程?

单核或多核I/O密集型下使用:多线程

单核计算密集型下使用:多线程

多核计算密集型下使用:多进程

多cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能

每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处

对于一个程序来说不可能是纯IO型或者纯计算型,我们只能相对的判断是IO密集型还是计算密集型,来选择多进程还是多线程

单核情况下:

​ 开启四个任务是计算密集型的,没有多核来并行计算,开多个进程,只是徒增进程的开销内存资源,应该使用多线程

​ 开启四个任务是IO密集型的,开启多进程也是徒增,来回切换的速度还不如开启多线程的,所以应该使用多线程

多核情况下:

​ 开启四个任务是计算密集型的,多核意味着多个CPU去计算,开启多进程可以同一时刻去计算,所以应该使用多进程

​ 开启四个任务是IO密集型的,再多的核也在在等待,来回切换的速度进程不如线程的,所以应该使用多线程

5、多线程多进程多核下性能测试

from multiprocessing import Process
from threading import Thread
import os
import time # 计算密集型
def task1():
i = 0
for line in range(110000000):
i += 1 if __name__ == '__main__':
print(os.cpu_count()) # 查看计算机几核的
list1 = []
start_time = time.time()
for i in range(4):
p1 = Process(target=task1) # 4进程下: 17.369488954544067
# t1 = Thread(target=task1) # 4线程下: 27.991361618041992
p1.start()
# t1.start()
# list1.append(t1)
list1.append(p1)
for i in list1:
i.join()
end_time = time.time()
print(end_time - start_time) # IO密集型
def task2():
time.sleep(1) if __name__ == '__main__':
print(os.cpu_count())
start_time = time.time()
list2 = []
for i in range(40):
# p2 = Process(target=task2) #40进程下: 11.374541282653809
t2 = Thread(target=task2) # 40线程下: 1.010239839553833
# p2.start()
t2.start()
# list2.append(p2)
list2.append(t2)
for i in list2:
i.join()
end_time = time.time()
print(end_time - start_time)

协程

1、什么是协程

进程:资源单位

线程:执行单位

协程:单线程下实现并发

在I/O密集型的情况下,使用协程提高执行效率

手动的实现在同一线程下 “ 遇到I/O切换+保存状态 ” 让操作系统误以为没有I/O操作,将CPU执行权限继续交给你

即:在单线程下实现多个任务遇到IO就切换可以降低单线程的IO时间,从而最大限度的提升单线程的效率

2、实现协程

gevent模块:遇到I/O自动切换并保存状态

使用gevent模块中的monkey,monkey.patch_all()来监视是否遇到IO操作,再使用spawn来创建协程,使用joinall替代join,使协程运行完再结束线程,joinall中放入得到的对象到列表中

from gevent import spawn
from gevent import joinall
from gevent import monkey
import time # 补丁:监听所有的任务是否有IO操作
monkey.patch_all() def task1(name):
print(f'{name}开始')
time.sleep(1)
print(f'{name}结束') def task2():
print('task2开始')
time.sleep(3)
print('task2结束') def task3():
print('task3开始')
time.sleep(5)
print('task3结束') if __name__ == '__main__':
start_time = time.time()
# 创建协程
sp1 = spawn(task1,'task1')
sp2 = spawn(task2)
sp3 = spawn(task3)
# sp1.join()
# sp2.join()
# sp3.join()
joinall([sp1, sp2, sp3]) # 相当于 sp.join(),注意放入列表中
end_time = time.time()
print(end_time - start_time)
# task1开始
# task2开始
# task3开始
# task1结束
# task2结束
# task3结束
# 5.013161897659302

GIL全局解释器锁及协程的更多相关文章

  1. GIL全局解释器锁、协程运用、IO模型

    GIL全局解释器锁 一.什么是GIL 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C是一套语言(语法)标准,但是可以用不 ...

  2. python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程

    GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...

  3. 进程、线程与GIL全局解释器锁详解

    进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...

  4. Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)

    一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...

  5. Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁

    本节内容: 进程与线程区别 线程 a)  语法 b)  join c)  线程锁之Lock\Rlock\信号量 d)  将线程变为守护进程 e)  Event事件 f)   queue队列 g)  生 ...

  6. 15 GIL 全局解释器锁 C语言解决 top ps

    1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...

  7. 【转】进程、线程、 GIL全局解释器锁知识点整理

    转自:https://www.cnblogs.com/alex3714/articles/5230609.html 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线 ...

  8. 网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  9. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

随机推荐

  1. apache2 不支持php文件 解决办法

    一.修改apache配置文件 vim /usr/local/apache2/conf/httpd.conf 1.在此加上index.php <IfModule dir_module> Di ...

  2. Servlet的Listener介绍

    当Web应用在Web容器中运行时,Web应用内部会不断地发生各种事件:如Web应用被启动.Web应用被停止.用户session开始.用户session结束等.通常这些Web操作对开发者是透明的.但Se ...

  3. (三)golang--执行流程分析

    XXX.go--go build XXX.go--XXX.exe XXX.go--go run XXX.go 两种方式的区别:(1)如果我们先编译生成了可执行文件,那么我们可以将该可执行文件拷贝到没g ...

  4. Zookeeper 运维实践手册

    Zookeeper是一个高可用的分布式数据管理与协调框架,该框架能很好地保证分布式环境中数据一致性.一般用来实现服务发现(类似DNS),配置管理,分布式锁,leader选举等. 一.生产环境中Zook ...

  5. mybatis使用associaton进行分步查询

    Employee类 public class Employee { private Integer id; private String lastName; private String email; ...

  6. Linux常用命令:fdisk mkfs mount umount fstab实现自动挂载

    写在前 记录点常用命令,fdisk mkfs mount和umount,以及fstab实现自动挂载 fdisk fdisk主要用于操作硬盘的分区表.分区,下面简单记一点最常用的部分 查看当前系统识别到 ...

  7. Linux 笔记 - 第二十四章 配置 Tomcat

    一.前言 Tomcat 是 Apache 软件基金会(Apache Software Foundation)Jakarta 项目中的核心项目,由 Apache.Sun 和其他一些公司及个人共同开发.使 ...

  8. c#多个按钮执行同一类事件-按钮按下和弹起

    首先在Winform中添加一个Button控件,在属性里面为控件添加鼠标按下和弹起事件(不要双击按钮,在属性里面添加) 再添加其他几个按钮控件,在控件的属性里面为鼠标按下和弹起添加已定义好处理函数(M ...

  9. 【翻译】tus----一个可续传文件上传的开放协议

    tus tus是一个可续穿文件上传协议,它以Http协议为载体,统一了一个文件断点续传的标准. 这篇文章翻译自https://tus.io/ 目前该协议版本信息如下: Version: 1.0.0 ( ...

  10. vertx 异步编程指南 step8-使用RxJava进行反应式编程

    vertx 异步编程指南 step8-使用RxJava进行反应式编程 2018-04-23 13:15:32 zyydecsdn 阅读数 1212  收藏 更多 分类专栏: vertx   到目前为止 ...