day36 GIL锁与线程池
多进程与多线程效率对比
#
# """
#
# 计算密集型
# """
# from threading import Thread
# from multiprocessing import Process
# import time
#
# a = 1
# def task():
# global a
# for i in range(10000000):
# a +=1
# a * 10 / 2 - 3
#
# s = time.time()
# #多线程
# # t1 = Thread(target=task)
# # t2 = Thread(target=task)
# # t3 = Thread(target=task)
#
# if __name__ == '__main__':
#
# # 多进程
# t1 = Process(target=task)
# t2 = Process(target=task)
# t3 = Process(target=task)
# t1.start()
# t2.start()
# t3.start()
#
# t1.join()
# t2.join()
# t3.join()
#
# print(time.time() - s)
#
"""
IO型任务
"""
from threading import Thread
from multiprocessing import Process
import time
def task():
# for i in range(10):
with open(r"D:\脱产5期内容\day34\视频\1.线程理论.mp4",mode="rb")as f:
while True:
data = f.read(1024)
if not data:
break
s = time.time()
if __name__ == '__main__':
# 多线程
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
# 多进程
# t1 = Process(target=task)
# t2 = Process(target=task)
# t3 = Process(target=task)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(time.time() - s)
GIL锁
什么是GIL
全局解释器锁,是加在解释器上的互斥锁
只存在于cpython解释器中
python的内存回收管理机制,简称GC
GIL的加锁与解锁时机
加锁的时机:在调用解释器时立即加锁
解锁时机:
当前进程遇到IO或超时
为什么需要GIL
由于cpython的内存管理是非线程安全的,于是cpython就给解释器加了个锁,解决了安全问题,但是降低了效率,虽然有解决方 案,但是由于牵涉太多,一旦被修改,很多以前的基于GIL的程序都需要修改,所以变成了历史遗留问题
GIL带来的问题
即使在多核处理器情况下,也无法真正的并行
先有多线程模块,有这个问题,所以后来有了多进程模块弥补这个问题
总结:
1.在单核情况下,无论是IO密集型还是计算密集,HIL都不会产生影响
2.如果是多核下,IO密集型会受到GIl的影响,但是很明显IO速度比计算速度慢
3.IO密集型多线程, 因为多线程开销小,节省资源,对于计算密集型,应该使用多进程,因为在cpytho中多线程是无法并行的
GIL与线程锁的区别
from threading import Thread,Lock
import time
lock = Lock()
a = 0
def task():
global a
lock.acquire()
temp = a
time.sleep(0.01)
a = temp + 1
lock.release()
ts = []
for i in range(10):
t1 = Thread(target=task)
t1.start()
ts.append(t1)
for i in ts:
i.join()
print(a)
GIL使用用于保护解释器相关的数据,解释器也是一段程序,肯定有其定义各种数据
GIL并不能保证自己定义的数据的安全,所有一旦
多核cpu中,进程可以并行,线程不能并行
多线程TCP
客户端
from threading import Thread
import socket
c = socket.socket()
c.connect(("127.0.0.1",8989))
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
服务器端
from concurrent.futures import ThreadPoolExecutor
from threading import Thread
import socket
server = socket.socket()
server.bind(("127.0.0.1",8989))
server.listen()
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()
# t = Thread(target=task,args=(client,))
# t.start()
pool.submit(task,client)
线程池与进程池
池为容器,本质上就是一个存储进程或线程的列表
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import active_count,current_thread
import os,time
# 创建线程池 指定最大线程数为3 如果不指定 默认为CPU核心数 * 5
# pool = ThreadPoolExecutor(3)# 不会立即开启子线程
#
# print(active_count())
#
# def task():
# print("%s running.." % current_thread().name)
# time.sleep(1)
#
# #提交任务到线程池
# for i in range(10):
# pool.submit(task)
#
# 创建进程池 最大进程数为3 默认为cpu个数
pool = ProcessPoolExecutor(3)# 不会立即开启子进程
# time.sleep(10)
def task():
print("%s running.." % os.getpid())
time.sleep(1)
if __name__ == '__main__':
# #提交任务到进程池
for i in range(10):
pool.submit(task) # 第一次提交任务时会创建进程 ,后续再提交任务,直接交给以及存在的进程来完成,如果没有空闲进程就等待
# 与信号量的区别 ,信号量也是一种锁 适用于保证同一时间能有多少个进程或线程访问
# 而线程/进程池,没有对数据访问进行限制仅仅是控制数量
同步与异步
"""
阻塞 非阻塞
程序遇到了IO操作,无法继续执行代码,叫做阻塞
程序没有遇到IO操作,正常执行中,就叫非阻塞
它们指的是程序的状态
就绪 运行 阻塞
就绪和阻塞给人的感觉就是卡主了
同步 异步
同步(调用/执行/任务/提交),发起任务后必须等待任务结束,拿到一个结果才能继续运行
异步 发起任务后不需要关系任务的执行过程,可以继续往下运行
异步效率高于同步
但是并不是所有任务都可以异步执行,判断一个任务是否可以异步的条件是,任务发起方是否立即需要执行结果
同步不等于阻塞 异步不等于非阻塞
当使用异步方式发起任务时 任务中可能包含io操作 异步也可能阻塞
同步提交任务 也会卡主程序 但是不等同阻塞,因为任务中可能在做一对计算任务,CPU没走
"""
# 使用线程池 来执行异步任务
from concurrent.futures import ThreadPoolExecutor
import time
pool = ThreadPoolExecutor()
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就是一异步的方式提交任务
# print(f)
# print(f.result()) # result是阻塞的 会等到这任务执行完成才继续执行 ,会异步变成同步
fs.append(f)
# 是一个阻塞函数,会等到池子中所有任务完成后继续执行
pool.shutdown(wait=True)
# pool.submit(task,1) # 注意 在shutdown之后 就不能提交新任务了
for i in fs:
print(i.result())
print("over")
使用线程池 来发起异步任务
阻塞函数
pool.shutdown()
同步不是阻塞,异步也不完全是非阻塞,也有可能阻塞
day36 GIL锁与线程池的更多相关文章
- GIL锁、进程池与线程池
1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...
- python GIL锁、进程池与线程池、同步异步
一.GIL全局解释器锁 全局解释器锁 在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本机线程同时执行Python代码.之所以需要这个锁,主要是因为CPython的内存管理不是线 ...
- GIL锁、进程池与线程池、同步异步
GIL锁定义 GIL锁:Global Interpreter Lock 全局解释器 本质上是一把互斥锁 官方解释: 在CPython中,这个全局解释器锁,也称为GIL,是一个互斥锁,防止多个线程在同 ...
- GIL全局解释器锁,线程池与进程池 同步异步,阻塞与非阻塞,异步回调
GIL全局解释器锁 1.什么是GIL 官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents ...
- GIL、进/线程池、同/异步、阻/非阻塞
1 GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点: 保证Cpython解释器内存管理 ...
- Java多线程总结(二)锁、线程池
掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...
- python网络编程--线程(锁,GIL锁,守护线程)
1.线程 1.进程与线程 进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率.很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观 ...
- 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)
GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...
- 线程锁,threadinglocal,线程池,生产者消费者模型
1.线程锁 1.锁Lock(只能锁一次) import threading import time v = [] lock = threading.Lock() def func(arg): lock ...
随机推荐
- The Tower of Babylon(UVa 437)
题意:有n种立方体,每种都有无穷多个.选一些正方体摞成一根尽量高的柱子(可以选择任意一条边做高),使得每个立方体的底面长宽分别严格小于它下方的立方柱的底面长宽. 题解:可以套用DAG最长路算法,可以使 ...
- python gevent自动挡的协程切换。
import gevent def func(): print('running func 111')#第一步运行 gevent.sleep(2)#切换到下个协程 print('running fun ...
- [JLOI2011]不重复数字
原题链接 题解 题目大意:给出N个数,要求把其中重复的去掉,只保留第一次出现的数.最后按顺序输出N <= 50000 然这题是个哈希的典型题目 HASH,我对于它的理解就是一个桶%一个数,当然并 ...
- sql 不够七位数 在左侧自动补零 ,并循环插入N条记录
select right(cast('0000000000'+rtrim(字段) as varchar(20)),7) declare @i intdeclare @qid int set @i=1s ...
- 【python】*与**
1. 加了星号(*)的变量名会存放所有未命名的变量参数,不能存放dict,否则报错. 如: 1 def multiple(arg, *args): 2 print "arg: ", ...
- 关于bit,bin文件的一些研究
关于bit,bin文件的一些研究 bit文件里面有head information 但bin文件里面并不包含 bit 文件里面包含如下信息 SPI flash 时钟需要用到的源语 watchdog 设 ...
- MySQL Point in Time Recovery the Right Way
In this blog, I’ll look at how to do MySQL point in time recovery (PITR) correctly. Sometimes we nee ...
- SQL注入检测
目前只支持单个对象,不支持对象中包含对象 /// <summary> /// 检查SQL中的非法字符 /// </summary> public class SQLInject ...
- Wireshark win7 没有找到接口;找不到接口
下载安装winpcap: https://www.winpcap.org/install/default.htm
- ionic3 热更新发布步骤记录
1.安装基本框架npm install -g ionic@latest npm install -g cordova ionic 验证版本号 ionic –version cordova -versi ...