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进程中只有一份解释器,如 ...
随机推荐
- EF调用sql语句
1.连接数据库 2.在Dal进行调用sql语句 public List<UserInfo> PageShow(out int totalcount,out int totalpage, s ...
- 《JavaScript高级程序设计》Chapter03 JavaScript语言基础
目录 Syntax Variable var let const Data Type Undefined Null Boolean Number String Symbol Object Operat ...
- django orm性能优化
参考: django 分页查询大表,很慢 面试小知识:MySQL索引相关 MySQL 用 limit 为什么会影响性能? 前言 orm性能优化是一件很重要的事,一般万条以上的数据都需要优化处理了. 这 ...
- 在Win7的64位系统中安装最新版Eclipse或STS
Eclipse版本为:eclipse-jee-2021-12-R-win32-x86_64 STS版本为:sts-4.13.1.RELEASE 这两个版本中都自带了17.0.1的jre插件,默认会使用 ...
- 解决VUE中document.documentElement.scrollTop为0(转)
原文地址:https://blog.csdn.net/WDCCSDN/article/details/82107374 Vue中document.documentElement.scrollTop的值 ...
- 关于uni-app开发的微信小程序顶部导航条机型适配
背景: 小程序顶部导航栏那里的样式和功能都是小程序自带的,当我们在pages.json里的pages里新加一条页面配置时,会自动生成一个带顶部导航栏的空白页面,当然也可以再配置里"navig ...
- 使用.pem密钥文件登录服务器
一.使用puttygen工具将.pem文件转成.ppk文件 Load时,需注意选择文件类型为All Files 二.使用secureCRT工具登录 点击properties...按钮,上传ppk文件, ...
- 记录linux上无法和本地传输文件
在学习docker搭建nacos的过程中,涉及到上传本地文件,但是包括从xshell直接拖拽还是xftp上传,都是失败, 最后百度查找多种不同的结果,最后实验下来是文件夹没有权限的问题. 解决步骤如下 ...
- 【StoneDB 模块介绍】服务器模块
[StoneDB 模块介绍]服务器模块 一.介绍 客户端程序和服务器程序本质上都是计算机上的一个进程,客户端进程向服务器进程发送请求的过程本质上是一种进程间通信的过程,StoneDB 数据库服务程序作 ...
- 搭建rust开发环境
1.打开https://www.rust-lang.org/tools/install 下载64位安装器 选择第一项默认安装 安装器会下载安装rust 相关工具链,并添加path C:\Users\z ...