Python进阶----GIL锁,验证Cpython效率(单核,多核(计算密集型,IO密集型)),线程池,进程池
day35
一丶GIL锁
什么是GIL锁:
存在Cpython解释器,全名:全局解释器锁.(解释器级别的锁)
GIL是一把互斥锁,将并发运行变成串行.
在同一个进程下开启的多个线程,同时只能有一个线程执行,无法利用多核优势
GIL锁的作用:
保证同一时间内,共享数据只能被一个任务修改.保证数据的完整性和安全性
自动上锁和解锁,不需要人为的添加.减轻开发人员的负担
所谓诟病:单进程的多线程不能利用多核
通常有人会认为GIL锁不能利用多核处理任务,是Python语言的诟病.个人认为任何一门语言都不是完美的,python问世于20世纪末,当时的CPU也只是单核.
So,不能利用多核的原因是:同一个进程下,只允许一个线程对共享内容进行修改.不允许多线程同时处理共享数据.
(打个比方:现在你家有10升(共享数据:10)牛掰的牛奶,你免费送给大家每人1升. 现在有100个人(100个线程)知道了这件事,都上你家来取奶.肯定谁先来,先得. 现在来了10个人(10个线程),每个人都说我去了1升,还剩9升.你真的还剩9升吗? 毛线~~ ,你球都不剩了. 后面来的90个人还能拿到奶吗? 肯定拿拿不到了. So你是不是得上锁,比如你家大门就是一把锁.每次只允许进来(上锁)1个人去奶.取完之后把总的奶量 减一. 第一个取完了出了大门(解锁).剩余的99个人开始抢着进你家门,公平竞争,谁先到你家门,先进就把门锁上了此时发现奶的数量还剩9升,第二个人也只取1升....往后依次延续,当第十一个人进来时,肯定奶已经没了.就表示数据为0.不能再取奶.保证奶的数量的安全性,和完整性(这还是装奶的容器))
GIL抽象图:
黑色方框就代表GIL锁
二丶验证Cpython的并发效率
需求:
现在有4个任务(计算密集型任务 或者 IO密集型任务)需要处理.
方案:
一.开启四个进程
二.开启一个进程,四个线程
结果:
单核:
IO密集型:开启进程开销大,进程切换速度远不如线程. 采用一个进程四个线程方案
计算密集型:没有多核来并行计算,徒增创建进程时间,采用一个进程四个线程方案
多核:
IO密集型:尽管多核,开启进程也比较耗时,而且还是要不断的切换.不如线程快.采用一进四线方案
计算密集型:多核,开启进程并行计算.此时如果用四个线程来会切换回损耗时间.采用四进程方案
多核处理计算密集型:
多进程的并行执行 比 单进程的多线程 效率高
# -*-coding:utf-8-*-
# Author:Ds
### 计算密集型
#开启四个进程 , 开启四个线程
from multiprocessing import Process
from threading import Thread
import time
import os
def task1():
res=1
for i in range(1,100000000):
res+=i
def task2():
res=1
for i in range(1,100000000):
res+=i
def task3():
res=1
for i in range(1,100000000):
res+=i
def task4():
res=1
for i in range(1,100000000):
res+=i
if __name__ == '__main__':
start_time=time.time()
### 多核四进程: 处理计算密集型任务,效率高
# 开启四个进程
# p1=Process(target=task1,) # 6.557461261749268
# p2=Process(target=task2,)
# p3=Process(target=task3,)
# p4=Process(target=task4,)
### 虽然本人计算机是多核,但是由于GIL所的原因,同一时刻只允许一个线程处理任务
### 一进程四线程: 处理计算密集型任务,效率低
#开启四个线程
p1=Thread(target=task1,) # 22.048070430755615
p2=Thread(target=task2,)
p3=Thread(target=task3,)
p4=Thread(target=task4,)
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print(f'主:{time.time()-start_time}')
#### 总结:
#计算密集型: 多进程的并行执行 ~比~ 单进程的多线程 效率高
多核处理IO密集型:
任务是IO密集型并且任务数量很大,用单进程下的多线程效率高.
from multiprocessing import Process
from threading import Thread
import time
import os
def task1():
res=1
time.sleep(3)
if __name__ == '__main__':
start_time=time.time()
### 并行处理 四核 开启一个进程,使用一个CPU
# 开启进程需要耗费大量时间
# l_t=[]
# for i in range(150):
# ### 多进程处理IO密集型
# p=Process(target=task1) # 耗时: 9.513447999954224
# l_t.append(p)
# p.start()
#
# for j in l_t:
# j.join()
### 并发处理
#虽然是并发处理 ,但是会在CPU之间来回切换.提高效率
l_t = []
for i in range(150):
### 多线程处理IO密集型
p = Thread(target=task1) # 耗时: 3.0212857723236084
l_t.append(p)
p.start()
for j in l_t:
j.join()
print(f'主:{time.time()-start_time}')
#### 总结:
#IO密集型: 任务是IO密集型并且任务数量很大,用单进程下的多线程效率高.
三丶GIL与互斥锁的关系
GIL vs ThreadLock:
GIL保护的是解释器级的数据,自动上锁,自动解锁.
Lock是保护用户自己的数据,手动上锁,手动解锁.如下图:
Python进阶----GIL锁,验证Cpython效率(单核,多核(计算密集型,IO密集型)),线程池,进程池的更多相关文章
- Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池
Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- GIL 线程池 进程池 同步 异步 阻塞 非阻塞
1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...
- GIL 线程池 进程池 同步 异步
1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...
- Python并发编程之线程池/进程池--concurrent.futures模块
一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/ ...
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ...
- 并发编程~~~多线程~~~计算密集型 / IO密集型的效率, 多线程实现socket通信
一 验证计算密集型 / IO密集型的效率 IO密集型: IO密集型: 单个进程的多线程的并发效率高. 计算密集型: 计算密集型: 多进程的并发并行效率高. 二 多线程实现socket通信 服务器端: ...
- Python并发编程之线程池&进程池
引用 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我 ...
- Python进阶:GIL(全局解释器锁)
一个不解之谜 一段代码 def CountDown(n): while n > 0: n -= 1 # CountDown(100000000) #==8秒 from threading imp ...
随机推荐
- 【技术博客】Git Flow模型管理代码版本
参考GIT版本管理:Git Flow模型,在此基础上加入了自己的理解,增加人员分工和相应代码,并根据本次项目的实际情况进行相应修改. 在本学期的软件工程开发过程中,我们从alpha阶段就使用了git ...
- 【转】Spring Boot @Condition 注解,组合条件你知道吗
原文:https://www.cnblogs.com/FraserYu/p/11280420.html 上一篇文章 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一 ...
- js中[object Object]与object.prototype.toString.call()
最近在用node读取文件中的json数据后,用JSON.parse()转成了json,然后响应数据传给前端,发现输出值object对象时显示[object object],在这里我们来看一下他的具体意 ...
- 【Python】解析Python中的文件操作
目录结构: contents structure [-] 简介 Python中的文件类型 内置函数的文件操作 open()函数 Mode 创建文本文件 读取文本文件 循环文件对象 关闭文件 With语 ...
- 类加载器ClassLoader源码解析
1.ClassLoader作用 类加载流程的"加载"阶段是由类加载器完成的. 2.类加载器结构 结构:BootstrapClassLoader(祖父)-->ExtClassL ...
- python初级(302) 5 列表
一.复习 1.函数的创建 1) def关键字 2) 函数名及后面跟随的括号 3)冒号加上函数体 2.函数的调用 函数名及后面跟随的括号 3.带一个,二个,三个参数的函数及调用 二.列表 family ...
- Spring BeanFactory 初始化 和 Bean 生命周期
(version:spring-context-4.3.15.RELEASE) AbstractApplicationContext#refresh() public void refresh() t ...
- python 中的eval与exec
eval类似exec,是使用python编译器运行表达式和语句两者区别在于:eval是编译表达式并返回值(如: eval("'hello'*2") 结果是 hellohello)e ...
- JVM Server与Client运行模式
JVM Server模式与client模式启动,最主要的差别在于:-Server模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升.原因是: 当虚拟机运行在-client模式的时候,使用的 ...
- Python知识点总结篇(三)
文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量: 通过句柄对文件进行操作: 关闭文件: with:自动关闭文件: with open('log', 'r') as f: ... 文件 ...
