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. python运维开发常用模块(四)文件对比模块difflib

    1.difflib介绍 difflib作为 Python的标准库模块,无需安装,作用是对比文本之间的差异,且支持 输出可读性比较强的HTML文档,与Linux下的diff命令相似.我们可以 使用dif ...

  2. kafka的安装和初步使用

    简介 最近开发的项目中,kafka用的比较多,为了方便梳理,从今天起准备记录一些关于kafka的文章,首先,当然是如何安装kafka了. Apache Kafka是分布式发布-订阅消息系统. Apac ...

  3. 是时候解决 students's Test 假设检验(显著性检验)了

    T test 由来已久 T 检验的概念 假设检验的步骤 假设检验可以分为三步: 建立检验假设和确定检验水准 单侧检验与双侧检验 选定检验方法和计算检验统计量 确定P值和做出推断结论 假设检验的两类错误 ...

  4. POJ 1306 暴力求组合数

    Combinations Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11049   Accepted: 5013 Des ...

  5. 基础知识---const、readonly、static

    const:静态常量,也称编译时常量(compile-time constants),属于类型级,通过类名直接访问,被所有对象共享! a.叫编译时常量的原因是它编译时会将其替换为所对应的值: b.静态 ...

  6. python]用eval强制将字符串转换为字典变量时候出错:NameError: name 'null' is not defined[python]用eval函数 字符串转dict

    本博客已搬家至个人网站 在路上 - On the way 下面的 技术 分类. 你可以通过点击 更新帖子 [已解决]Python中,用eval强制将字符串转换为字典变量时候出错:NameError: ...

  7. GET请求的请求参数最大长度

    在HTTP规范RFC-2616中有这样一段描述: The HTTP protocol does not place any a priori limit on the length of a URI. ...

  8. net输出错误日志

    在使用net开发webapi的时候,有时候程序异常了,外面只能看到一个错误:an error occur 怎么才能将具体的 错误堆栈信息输出来呢? 1.在startup.cs文件中添加如下代码就可以将 ...

  9. css画三角形原理解析

    <div id="div1"></div><div id="div2"></div><div id=&qu ...

  10. .net 调用 Python脚本中的代码

    使用工具:IronPython 工具介绍:是一种在 .NET 及 Mono上的 Python 实现,是一个开源的项目,基于微软的 DLR 引擎.(个人理解就是在 .net上面运行Python代码) 使 ...