GIL和池的概念
1.GIL概念
1. 什么是GIL(为Cpython解释器)
GIL本身就是一把互斥锁. 原理都一样. 都是让并发的线程同一时间只能执行一个
所以有了GIL的存在. 同一进程下的多个线程同一时刻只能有一个能运行. 无法实现并行 -> 意味着无法利用多核优势 -> 多个CPU同时计算
GIL是影响python运行效率慢的原因之一. 但是不影响并发的执行. 只是无法同时利用多个cpu执行计算
GIL可以被比喻成执行权限. 同一进程下的所有线程要想运行代码都要先抢执行权限
2. 为何要有GIL:
因为Cpython中自带的垃圾回收机制不是线程安全的 -> 需要将GIL锁加在Cpython之上. 控制只能有一个线程在执行.
抢到GIL才能去执行
3. 如果使用:
GIL vs 自定义的互斥锁
GIL相当于执行任务. 会在任务无法执行时. 被强迫释放
自定义互斥锁. 即便是无法执行. 也不回自动释放
4. 多线程执行IO密集型任务会大幅提升效率: 多线程发送网络请求
执行CPU密集型任务反而会降低效率. 因为频繁切换切换线程导致无意义的时间消耗.产生CPU颠簸. CPU负责计算.程序出现io什么都做不了
CPU密集型任务可以使用多进程并发
5. 多线程的并发运行:
每个线程都要先执行请求GIL. 当线程阻塞时(例如IO阻塞). 线程释放GIL. 这时另外一个线程开始运行
操作系统将时间分成多个时间片去运行线程. 线程之间切换速度极快. 肉眼看起来就行是同时运行. 其实并不是同时运行
所以多线程只是并发. 看起来同时运行. 并非并行
2.线程queue
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 16:10
# @author: Maxs_hu
import queue
# 队列: 先进先出
q = queue.Queue(5)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
# 堆栈: 先进后出
q = queue.LifoQueue(5) # last in first out
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
# 优先级队列: 数字越小. 优先级越高
q = queue.PriorityQueue()
q.put((-1, 'data1'))
q.put((11, 'data2'))
q.put((200, 'data3'))
print(q.get())
print(q.get())
print(q.get())
# (-1, 'data1')
# (11, 'data2')
# (200, 'data3')
3.线程池
"""
1. 什么时候用池:
池的功能是限制启动的进程数量或线程数
什么时候应该限制???
当并发任务数远远超过了计算机承受能力时. 即无法一次性开启过多的进程数或线程数
就应该用池的概念将开启的进程数或者线程数限制在计算机可承受的范围内
2. 同步vs异步
同步和异步是提交任务的两种方式
同步: 类似于串行. 任务提交后等待返回值返回. 再提交下一个任务(和异步对比...基本不用)
异步: 提交完任务后不会在原地等待. 直接运行下一行代码. 等到任务有返回值后会自动触发回调函数
"""
from concurrent.futures import ThreadPoolExecutor # 线程池启动器 concurrent 能够同时发生的
import time
# =====程序无返回值时=====
def func(name):
for i in range(10):
print(name, i)
if __name__ == '__main__':
with ThreadPoolExecutor(9) as t:
# 直接将三百个submit提交给线程池
for i in range(100):
t.submit(func, "周杰伦") # submit 提交
t.submit(func, "薛之谦")
t.submit(func, "林俊杰")
# =====程序有返回值时,且需要输出返回值时=====
def func(name, t):
time.sleep(t)
print(f"我叫{name}")
return name
def parse(res):
print(res.result()) # 注意要加括号
if __name__ == '__main__':
with ThreadPoolExecutor(3) as t:
t.submit(func, "薛之谦", 3).add_done_callback(parse) # callback返回即执行,但执行顺序是不确定的
t.submit(func, "许嵩", 2).add_done_callback(parse) # 这里自动执行,参数也是自动传递
t.submit(func, "林俊杰", 1).add_done_callback(parse)
# =====执行顺序确定的线程池=====
def func(name, t):
time.sleep(t)
print(f"my name is {name}")
return name
if __name__ == '__main__':
with ThreadPoolExecutor(3) as t:
result = t.map(func, ["薛之谦", "林俊杰", "许嵩"], [2, 1, 3]) # map 映射
for res in result:
print(res) # 返回值有特点,是因为多线程较快
# map的返回值是迭代器
# 打印的结果是有序的,且按照分配任务的顺序进行打印
4.进程池
# -*- encoding:utf-8 -*-
# @time: 2022/8/7 21:27
# @author: Maxs_hu
# 调用进程池(无返回值):
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import os
import time
def task(i):
print('%s is running %s' % (os.getpid(), i))
time.sleep(2)
if __name__ == '__main__':
with ProcessPoolExecutor(4) as p: # 创建进程池最多并发四个进程
for i in range(10): # 将9个任务交给进程池执行
p.submit(task, i) # 任务提交
# 进程池(有返回值) -> 返回值无序. 如果想要返回值有序. 则需要使用map函数提交任务
def task(i):
print('%s is running %s' % (os.getpid(), i))
time.sleep(2)
return i ** 2
def parse(res):
print(res.result())
if __name__ == '__main__':
with ProcessPoolExecutor(4) as p:
for i in range(10):
p.submit(task, i).add_done_callback(parse) # 任务提交之后出现返回值就会执行回调函数执行parse. 打印返回值
p.submit(task, i).add_done_callback(parse)
GIL和池的概念的更多相关文章
- python之路day06--python2/3小区别,小数据池的概念,编码的进阶str转为bytes类型,编码和解码
python2#print() print'abc'#range() xrange()生成器#raw_input() python3# print('abc')# range()# input() = ...
- IT题库9-线程池的概念和原理
在什么情况下使用线程池? 1.单个任务处理的时间比较短:2.需要处理的任务的数量大: 使用线程池的好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销.2.如不使用线程池,有可能造成系统创建 ...
- OC学习篇之---数组对象的引用计数问题和自动释放池的概念
之前一片文章中我们介绍了OC中的两个关键字@property和@synthesize的使用的使用: http://blog.csdn.net/jiangwei0910410003/article/de ...
- OSI传输层TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
目录 传输层之TCP与UDP协议 应用层 socket模块 socket基本使用 代码优化 半连接池的概念 传输层之TCP与UDP协议 TCP与UDP都是用来规定通信方式的 通信的时候可以随心所欲的聊 ...
- 11月16日内容总结——OSI传输层之TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
目录 一.传输层之TCP与UDP协议 1.TCP协议(重要) 三次握手建链接(白话版) 三次握手专业版 四次挥手断连接(白话版) 四次挥手专业版 2.UDP协议 3.tcp和udp的对比 二.应用层简 ...
- Python学习之GIL&进程池/线程池
8.6 GIL锁** Global interpreter Lock 全局解释器锁 实际就是一把解释器级的互斥锁 In CPython, the global interpreter lock, or ...
- id,is的用法,小数据池的概念及编码知识进阶
一:id 查询内存地址 name = 'alex' print(id(name)) li = [1,2,3] print(id(li)) 二:is 判断的是内存地址 name1 = 'alex@' ...
- 第三十八天 GIL 进程池与线程池
今日内容: 1.GIL 全局解释器锁 2.Cpython解释器并发效率验证 3.线程互斥锁和GIL对比 4.进程池与线程池 一.全局解释器锁 1.GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在 ...
- GIL 线程池 进程池 同步 异步 阻塞 非阻塞
1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...
- GIL 线程池 进程池 同步 异步
1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...
随机推荐
- drf(3)
1 不使用drf编写5个接口 1.1 路由 urlpatterns = [ path('books/', views.BookView.as_view()), path('books/&l ...
- K8s+Docker 学习笔记系列
学前知识 你需要掌握 Linux 的常用命令.你可以通过Linux 教程 来学习相关命令. Docker应用场景 Web 应用的自动化打包和发布. 自动化测试和持续集成.发布. 在服务型环境中部署和调 ...
- 多线程post
async Task<long> post() { var stopwatch = new Stopwatch(); stopwatch.Start(); var client = new ...
- 一道网红题:Java值传递,答案开始看了不太懂,是不是涉及到了匿名类的实例化?
题目如下:看起来是值传递的考察... public class Test{ public static void main(String[] args){ int a = 10; int b = 10 ...
- git的回退以及合并,删除什么的
有时候不小心合并了别的分支中的commit.我们需要回退某些提交记录.可以通过reset来操作,reset 会回退到指定commit.这种方式会删除记录,我们最好使用revert命令来操作 git r ...
- winform导出excel报'object' does not contain a definition for 'get_Range'的问题
现手上有个老项目采用.net framework3.0开发,改成4.0后,excel导出报'object' does not contain a definition for 'get_Range'的 ...
- 记一次FusionCompute安装springboot应用过程
客户给了一个地址,登录后发现是FusionCompute 的一个虚拟机,第一次使用,于是过了一下在线帮助文档 ,大概明白了. 因为客户已经创建完了裸机虚拟机,前面的过程我也不会太多关注. 在概要里,可 ...
- ASP.NET Web应用程序(.NET Framework)开发网站
1.创建项目 2.控制器脚本说明 [FromBody]JObject value:JObject此类型默认为string,但是string无法正常解析复杂类型的Json数据,所以修改为JObject类 ...
- 文件上传 upload-labs Pass-17 二次渲染
Pass-17 审计源码 $is_upload = false; $msg = null; if (isset($_POST['submit'])){ // 获得上传文件的基本信息,文件名,类型,大小 ...
- Java所用相关软件的大致安装流程
JAVA下载流程 一.相关环境的安装与配置 1.JDK的下载 去官网搜索相应的java版本,并进行下载 官网链接:www.xfdown.com/soft/125774.html在该链接下,可以下载ja ...