一.全局解释器锁

  1.GIL:全局解释器锁

    GIL本质就是一把互斥锁,是夹在解释器身上的

    统一进程内的所有线程都需要先抢到GIL锁,才能执行pai解释器代码

  2.GIL优缺点:

    优点:

      保证Cpython解释器内存管理的线程安全

    缺点:

      同一进程内所有的线程同一时刻只能有一个执行,

      也就是锁Cpython解释器多线程无法实现真正的并行

from threading import Thread,current_thread
import time def task():
print("%s is running"%current_thread().name)
time.sleep(3)
print("%s is done"current_thread().name) if __name__=="__main__":
t1=Thread(target=task)
t2=Thread(target=task)
t3=Thread(target=task)
t1.start()
t2.start()
t3.start()

二.Cpython解释器并发效率验证

关于GIL性能的讨论

解释器加锁以后
将导致所有线程只能并发 不能达到真正的并行 意味着同一时间只有一个CPU在处理你的线程
给你的感觉是效率低

代码执行有两种状态
阻塞 i/o 失去CPU的执行权 (CPU等待IO完成)
非阻塞 代码正常执行 比如循环一千万次 中途CPU可能切换 很快会回来 (CPU在计算)

假如有32核CPU 要处理一个下载任务 网络速度慢 100k/s 文件大小为1024kb
如果你的代码中IO操作非常多 cpu性能不能直接决定你的任务处理速度

案例:
目前有三个任务 每个任务处理需一秒 获取元数据需要一小时
3个CPU 需要 一小时1秒
1个cpu 需要 一小时3秒

在IO密集的程序中 CPU性能无法直接决定程序的执行速度 python就应该干这种活儿
在计算密集的程序中 CPU性能可以直接决定程序的执行速度

#计算密集型测试
from threading import Thread
from multiprocessing import Process
import time # 计算密集任务 def task1():
sum = 1
for i in range(10000000):
sum *= i def task2():
sum = 1
for i in range(10000000):
sum *= i def task3():
sum = 1
for i in range(10000000):
sum *= i def task4():
sum = 1
for i in range(10000000):
sum *= i def task5():
sum = 1
for i in range(10000000):
sum *= i def task6():
sum = 1
for i in range(10000000):
sum *= i if __name__ == '__main__': # 开始时间
st_time = time.time()
# 多线程情况下
# t1 = Thread(target=task1)
# t2 = Thread(target=task2)
# t3 = Thread(target=task3)
# t4 = Thread(target=task4)
# t5 = Thread(target=task5)
# t6 = Thread(target=task6) t1 = Process(target=task1)
t2 = Process(target=task2)
t3 = Process(target=task3)
t4 = Process(target=task4)
t5 = Process(target=task5)
t6 = Process(target=task6) t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t6.start()
#
# t1.join()
# t2.join()
# t3.join()
# t4.join()
# t5.join()
# t6.join() print(time.time() - st_time)
from threading import Thread
from multiprocessing import Process
import time # 计算密集任务
def task1():
time.sleep(3) def task2():
time.sleep(3) def task3():
time.sleep(3) def task4():
time.sleep(3) def task5():
time.sleep(3) def task6():
time.sleep(3) if __name__ == '__main__': # 开始时间
st_time = time.time()
# 多线程情况下
# t1 = Thread(target=task1)
# t2 = Thread(target=task2)
# t3 = Thread(target=task3)
# t4 = Thread(target=task4)
# t5 = Thread(target=task5)
# t6 = Thread(target=task6) t1 = Process(target=task1)
t2 = Process(target=task2)
t3 = Process(target=task3)
t4 = Process(target=task4)
t5 = Process(target=task5)
t6 = Process(target=task6) t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t6.start() # t1.join()
# t2.join()
# t3.join()
# t4.join()
# t5.join()
# t6.join() print(time.time() - st_time)

三.GIL与互斥锁

from  threading import Thread,Lock
import time mutex = Lock()
num = 1
def task():
global num
# print(num)
mutex.acquire()
temp = num
print(temp)
time.sleep(1) # 当你们线程中出现io时 GIL锁就解开
num = temp + 1
mutex.release() # 线程任务结束时GIL锁解开 t1 = Thread(target=task,) t2 = Thread(target=task,)
t1.start()
t2.start()
t1.join()
t2.join()
print(num)

GIL 和自定义互斥锁的区别

全局锁不能保证自己开启的线程安全 但要保证解释器中的数据的安全

GIL 在线程调用解释器是 自动加锁 在IO阻塞时或线程执行完毕时 自动解锁

四.进程池和线程池

  进程池

    就是一个装进程的容器

  为什么出现

    当进程很多的时候方便管理进程

  什么时候用?

    当并发量特别大的时候 列入双十一

    很多时候进程是空闲的 就让他进入进程池 让有任务处理时才从进程取出来使用

  进程池使用

    ProcessPoolExecutor类

    创建时指定最大进程数 自动创建进程

    调用submit函数将任务提交进程池中

    创建进程是在调用submit后发生

  总结一下:

    进程池可以自动创造进程

    进程现在最大进程数

    自动选择一个空闲的进程帮你处理任务

  进程什么时候算是空闲?

    代码执行完算是空闲

  IO密集时 用线程池

  计算密集时 用线程池

思考

1、什么是GIL

GIL = Global Interpreter Lock (全局解释锁器锁)
2、有了GIL会对单进程下的多个线程造成什么样的影响

防止对个线程竞争统一资源造成数据的错乱,只能有一个线程进行读写操作.
3、为什么要有GIL

为了避免资源竞争造成的数据错乱
4、GIL与自定义互斥锁的区别,多个线程争抢GIL与自定义互斥锁的过程分析

GIL不保证自己开启线程的安全 但保证解释器中数据的安全

GIL 在线程调用解释其时 自动加锁 在IO阻塞是或线程代码执行完毕时,自动解锁
5、什么时候用python的多线程,什么时候用多进程,为什么?

2、进程池与线程池
1、池的用途,为何要用它

池用来存储线程和进程,可以方便进程和线程的管理
2、池子里什么时候装进程什么时候装线程?

计算密集时装进程,IO密集时装线程

3、基于进程池与线程池实现并发的套接字通信

#服务端

from socket import *
from threading import Thread
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor tpool=ThreadPoolExecutor(3) def communicte(conn,client_addr):
while True:
try:
data= conn.recv(1024)
if not data:break
conn.send(data.upper())
except ConnectionAbortedError:
break
conn.close() def server():
server = socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5) while True:
conn,client_addr=server.accept()
print(client_addr)
tpool.submit(communicte,conn,client_addr)
server.close() if __name__=='__main__':
server()
#客户端
import socket c = socket.socket()
c.connect(('127.0.0.1',8080))
while True:
msg = input(">>>:")
c.send(msg.encode("utf-8"))
data = c.recv(1024)
print(data.decode("utf-8"))

第三十八天 GIL 进程池与线程池的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. GIL,queue,进程池与线程池

    GIL 1.什么是GIL(这是Cpython解释器) GIL本质就是一把互斥锁,既然是互斥锁,原理都是一样的,都是让多个并发线程同一时间只能有一个执行 即:有了GIL的存在,同一进程内的多个线程同一时 ...

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

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

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

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

随机推荐

  1. 《React Native 精解与实战》书籍连载「iOS 平台与 React Native 混合开发」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  2. Linux提示删除文件cannot remove `文件名': Operation not permitted

    Linux系统下删除某个文件时提示如下报错: 执行lsattr命令可以看到隐藏属性-------i--------,如下图: 通过查找资料发现: chattr命令用于改变文件属性.这项指令可改变存放在 ...

  3. java问题

    Collection 和 Collections的区别? Collection是集合类的上级接口,继承与他的接口主要有Set 和List. Collections是针对集合类的一个帮助类,他提供一系列 ...

  4. Mysql 字符集及排序规则

    一.字符集 字符集:就是用来定义字符在数据库中的编码的集合. 常见的字符集:utf8.Unicode.GBK.GB2312(支持中文).ASCCI(不支持中文)   二.字符集排序规则   作者本人用 ...

  5. mysql常用命令行操作(二):表和库的操作、引擎、聚合函数

    一.查看.创建.删除数据库 create database library default character set utf8 collate utf8_general_ci; # 创建数据库并设置 ...

  6. h5小功能_classList和自定义属性data

    ###1.classList返回一个对象集 通过obj.classList.add()或obj.classList.remove()可操作对象的class属性值 classList.toggle( ) ...

  7. toTree

    // js实现树级递归, // 通过js生成tree树形菜单(递归算法) const data = [ { id: 1, name: "办公管理", pid: 0 }, { id: ...

  8. linux 安装ssh以及ssh用法与免密登录

    想要免费登录就是把本地机器的id_rsa_pub的内容放到远程服务器的authorized_keys里面 一.配置yum和hosts文件 配置hosts文件: 命令:vi /etc/hosts 在文件 ...

  9. java lang(Thread) 和 Runable接口

    public interface Runnable { public abstract void run(); } public class Thread implements Runnable { ...

  10. vue二次实战(一)

    创建好项目(npm run dev 运行项目:先不用运行,或先运行再关闭) 先安装axios! npm install axios 然后! npm install --save axios vue-a ...