一、GIL全局解释器锁

  • 全局解释器锁

    在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本机线程同时执行Python代码。之所以需要这个锁,主要是因为CPython的内存管理不是线程安全的。(然而,自从GIL存在以来,其他特性已经逐渐依赖于它所执行的保证)

    • 什么是GIL

      全局解释器锁, 施加在解释器上的互斥锁

    • 为什么需要GIL

      由于CPython的内存管理时非线程安全,于是CPython就给解释器加上锁, 解决了安全问题.

  • GIL的加锁与解锁时机

    • 加锁的时机: 在调用解释器时立即加锁

    • 解锁的时机:

      • 当前线程遇到了IO时

      • 当前线程执行时间超过设定值时 , 一旦达到某个阈值 , CPU会通知线程保存状态切换线程 , 以此来保证数据安全

  • 总结 : 由于GIL锁的特性 , 我们需要考虑什么情况下用多线程什么情况下用多进程

    • 在单核情况下 , 无论是IO密集型还是计算密集型 , GIL都不会产生影响,多线程会更加经济实惠.

    • 在多核情况下 , IO密集型会受到GIL的影响

      • 对于计算密集型 , 需要并行处理 , 所以需要用到多进程

      • 对于IO密集型 , 由于IO时间较长 , 创建进程不经济 , 所以应该用多线程

二、GIL带来的问题

  • GIL的优缺点:

    • 优点:保证Cpython解释器内存管理的线程安全

    • 缺点: ​ 同一进程内所有的线程同一时刻只能有一个执行, ​ 也就说Cpython解释器的多线程无法实现并行

三、线程池和进程池

  • 什么是进程/线程池

    池表示一个容器 , 那么进程或线程池表示的就是一个存放进程或线程的列表

  • 什么时候使用线程池/进程池

    如果是IO密集型任务使用线程池 , 如果是计算密集型任务则使用进程池

  • 多线程Tcp通信

  服务端

from concurrent.futures import ThreadPoolExecutor
from threading import Thread
import socket

server = socket.socket()
server.bind(("127.0.0.1",8806))
server.listen()

# 创建线程池 指定最大线程数为3 如果不指定 默认为CPU核心数 * 5
pool = ThreadPoolExecutor(3) # 不会立即开启子线程

def task(client):
while True:
try:
data = client.recv(1024)
if not data:
client.close()
break
client.send(data.upper())
except Exception:
client.close()
break while True:
client, addr = server.accept()
# submit:提交任务到线程池,第一次提交任务时会创建进程 ,后续再提交任务,直接交给以及存在的进程来完成,如果没有空闲进程就等待
pool.submit(task, client)
  客户端
from threading import Thread
import socket

c = socket.socket()
c.connect(("127.0.0.1",8806))

def send_msg():
while True:
msg = input(">>>:")
if not msg:
continue
c.send(msg.encode("utf-8"))

send_t = Thread(target=send_msg)
send_t.start()

while True:
try:
data = c.recv(1024)
print(data.decode("utf-8"))
except:
c.close()
break
 

四、自定义的线程锁与GIL的区别

GIL保护的是解释器级别的数据安全,比如对象的引用计数,垃圾分代数据等等,具体参考垃圾回收机制详解。

自定义线程锁保证的是进程内的资源在同一时间只能有一个线程去访问,保护的是进程内资源数据安全

四、同步与异步

阻塞与非阻塞:

阻塞 : 程序遇到IO操作,无法继续执行代码 , 叫做阻塞

非阻塞 : 没有阻塞 , 正常运行

同步与异步

提交任务的两种方式

  • 同步:

    发起任务后必须等待任务结束,拿到一个结果才能继续运行

  • 异步 : 提交任务后,不再原地等待,直接执行下一行代码,(执行结果?)

    异步效率高于同步

使用进程池 , 来实现异步任务

# 异步提交

from concurrent.futures import ThreadPoolExecutor
import time
pool = ThreadPoolExecutor() # 不设置线程池最大数量默认为CPU核心数*5


def task(i):

time.sleep(1)
print("sub thread run..")
i += 100
return i

fs = []
for i in range(10):
f = pool.submit(task,i) # submit就是一异步的方式提交任务,会返回一个对象,通过调用result方法获得结果
fs.append(f) # 将submit对象添加到列表中



# 是一个阻塞函数,会等到池子中所有任务完成后继续执行
pool.shutdown(wait=True) # 任务运行结束拿到结果后才会执行下一步

# pool.submit(task,1) # 注意 在shutdown之后 就不能提交新任务了

for i in fs:
print(i.result()) # 循环取执行结果

print("over")


# 将程序改为同步提交
from concurrent.futures import ThreadPoolExecutor
import time
pool = ThreadPoolExecutor() # 不设置线程池最大数量默认为CPU核心数*5


def task(i):

time.sleep(1)
print("sub thread run..")
i += 100
return i

for i in range(10):
f = pool.submit(task,i) # submit就是一异步的方式提交任务,会返回一个对象,通过调用result方法获得结果
res = f.result() # result是一个阻塞函数,不拿到结果不执行下一步

print(res)

print("over")

同步提交任务 , 程序卡住 , 不一定是阻塞,因为任务中可能在做一堆计算任务 , CPU没走开。

python GIL锁、进程池与线程池、同步异步的更多相关文章

  1. GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论

    昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...

  2. GIL锁、进程池与线程池

    1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...

  3. GIL解释锁及进程池和线程池

    官方介绍 ''' 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple nati ...

  4. GIL锁、进程池与线程池、同步异步

    GIL锁定义 GIL锁:Global Interpreter Lock  全局解释器 本质上是一把互斥锁 官方解释: 在CPython中,这个全局解释器锁,也称为GIL,是一个互斥锁,防止多个线程在同 ...

  5. GIL解释器锁 & 进程池与线程池

    今日内容 GIL 全局解释器锁(重要理论) 验证 GIL 的存在及功能 验证 python 多线程是否有用 死锁现象 进程池与线程池(使用频率高) IO模型 详细参考: https://www.bil ...

  6. 4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞

    一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点:  保 ...

  7. GIL与普通互斥锁区别,死锁现象,信号量,event事件,进程池与线程池,协程

    GIL与普通互斥锁区别 GIL锁和互斥锁的异同点 相同: 都是为了解决解释器中多个线程资源竞争的问题 异: 1.互斥锁是Python代码层面的锁,解决Python程序中多线程共享资源的问题(线程数据共 ...

  8. 第三十八天 GIL 进程池与线程池

    今日内容: 1.GIL 全局解释器锁 2.Cpython解释器并发效率验证 3.线程互斥锁和GIL对比 4.进程池与线程池 一.全局解释器锁 1.GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在 ...

  9. python 36 进程池、线程池

    目录 1. 死锁与递归锁 2. 信号量Semaphor 3. GIL全局解释器锁:(Cpython) 4. IO.计算密集型对比 4.1 计算密集型: 4.2 IO密集型 5. GIL与Lock锁的区 ...

  10. day37 GIL、同步、异步、进程池、线程池、回调函数

    1.GIL 定义: GIL:全局解释器锁(Global Interpreter Lock) 全局解释器锁是一种互斥锁,其锁住的代码是全局解释器中的代码 为什么需要全局解释器锁 在我们进行代码编写时,实 ...

随机推荐

  1. Net Core -- 配置Kestrel端口

    Net Core -- 配置Kestrel端口 Kestrel介绍 在Asp.Net Core中,我们的web application 其实是运行在Kestrel服务上,它是一个基于libuv开源的跨 ...

  2. java课后思考题(五)

    1.使用Files. walkFileTree()找出指定文件夹下所有扩展名为.txt和.java的文件. import java.io.IOException;import java.nio.fil ...

  3. mongodb 分片技术

    MongoDB Sharding Cluster 分片集群 规划:10个实例:38017-38026 (1)configserver:3台构成的复制集(1主两从,不支持arbiter)38018-38 ...

  4. git-gui:使用终端打开以后出现错误提示 Spell checking is unavable

    参考链接:http://www.lai18.com/content/10706682.html 安装了git-gui,打开以后出现以下提示: Spell checking is unavable: e ...

  5. Redhat/CentOS 软件安装

    概述 软件包简介 rpm 包安装 yum 在线安装 源码包管理 软件包分类 源码包 二进制包(rpm包.系统默认包) rpm包安装 rpm包的依赖性 树形依赖: a -> b -> c 环 ...

  6. 对flex-grow和flex-shrink的深入理解

    flex弹性布局,如果子元素宽度之和大于或者小于父元素宽度,空间就会存在剩余和不够,flex默认不换行,除非设置flex-wrap,那么这种情况下,有两个重要的属性,flex-grow和flex-sh ...

  7. Windows中将nginx添加到服务

    下载安装nginx http://nginx.org/en/download.html 下载后解压到C盘 C:\nginx-1.14.0 添加服务 需要借助"Windows Service ...

  8. zblog去除底部版权信息 “请勿修改或删除主题版权及作者信息”

    场景:使用了免费模板,但底部带作者版权.删除版权信息的代码后访问前台弹窗:请勿修改或删除主题版权及作者信息... 1. 删除版权信息代码 使用notepad++搜索功能,搜索版权信息:如ABC,找到相 ...

  9. static 关键字用法

    static a=0; 就是把a初始化为0:初始值为0而已 即使a是局部变量,每次进入此变量所在的函数,a值还是保持上次赋值: 在中断里建议在局部变量前加上static,以确保此变量值的寿命

  10. 使用as开发jni入门(附验证):配置ndk开发环境,配置as相关jni配置

    编写jni,生成so文件: 1.通过as内置的Android SDK下载需要使用的ndk,在系统环境变量设置相关参数 2.新建一个普通as项目,新建一个类,用来静态加载so库和书写本地native方法 ...