GIL全局解释器锁及协程
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全局解释器锁及协程的更多相关文章
- GIL全局解释器锁、协程运用、IO模型
GIL全局解释器锁 一.什么是GIL 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C是一套语言(语法)标准,但是可以用不 ...
- python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程
GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...
- 进程、线程与GIL全局解释器锁详解
进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...
- Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)
一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...
- Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁
本节内容: 进程与线程区别 线程 a) 语法 b) join c) 线程锁之Lock\Rlock\信号量 d) 将线程变为守护进程 e) Event事件 f) queue队列 g) 生 ...
- 15 GIL 全局解释器锁 C语言解决 top ps
1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...
- 【转】进程、线程、 GIL全局解释器锁知识点整理
转自:https://www.cnblogs.com/alex3714/articles/5230609.html 本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线 ...
- 网络编程之多线程——GIL全局解释器锁
网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...
- 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁
一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...
随机推荐
- python运维开发常用模块(四)文件对比模块difflib
1.difflib介绍 difflib作为 Python的标准库模块,无需安装,作用是对比文本之间的差异,且支持 输出可读性比较强的HTML文档,与Linux下的diff命令相似.我们可以 使用dif ...
- kafka的安装和初步使用
简介 最近开发的项目中,kafka用的比较多,为了方便梳理,从今天起准备记录一些关于kafka的文章,首先,当然是如何安装kafka了. Apache Kafka是分布式发布-订阅消息系统. Apac ...
- 是时候解决 students's Test 假设检验(显著性检验)了
T test 由来已久 T 检验的概念 假设检验的步骤 假设检验可以分为三步: 建立检验假设和确定检验水准 单侧检验与双侧检验 选定检验方法和计算检验统计量 确定P值和做出推断结论 假设检验的两类错误 ...
- POJ 1306 暴力求组合数
Combinations Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 11049 Accepted: 5013 Des ...
- 基础知识---const、readonly、static
const:静态常量,也称编译时常量(compile-time constants),属于类型级,通过类名直接访问,被所有对象共享! a.叫编译时常量的原因是它编译时会将其替换为所对应的值: b.静态 ...
- python]用eval强制将字符串转换为字典变量时候出错:NameError: name 'null' is not defined[python]用eval函数 字符串转dict
本博客已搬家至个人网站 在路上 - On the way 下面的 技术 分类. 你可以通过点击 更新帖子 [已解决]Python中,用eval强制将字符串转换为字典变量时候出错:NameError: ...
- GET请求的请求参数最大长度
在HTTP规范RFC-2616中有这样一段描述: The HTTP protocol does not place any a priori limit on the length of a URI. ...
- net输出错误日志
在使用net开发webapi的时候,有时候程序异常了,外面只能看到一个错误:an error occur 怎么才能将具体的 错误堆栈信息输出来呢? 1.在startup.cs文件中添加如下代码就可以将 ...
- css画三角形原理解析
<div id="div1"></div><div id="div2"></div><div id=&qu ...
- .net 调用 Python脚本中的代码
使用工具:IronPython 工具介绍:是一种在 .NET 及 Mono上的 Python 实现,是一个开源的项目,基于微软的 DLR 引擎.(个人理解就是在 .net上面运行Python代码) 使 ...