GIL以及协程

一、GIL全局解释器锁

  • 演示
'''
python解释器:
- Cpython c语言
- Jpython java 1、GIL:全局解释器锁
- 翻译:在同一个进程下开启的多个线程,同一时刻只能有一个线程执行,因为Cpython的内存管理不是线程安全。 - GIL全局解释器锁,本质上就是一把互斥锁,保证数据安全 定义:
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple
native threads from executing Python bytecodes at once. This lock is necessary mainly
because CPython’s memory management is not thread-safe. (However, since the GIL
exists, other features have grown to depend on the guarantees that it enforces.) 结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多多核优势。 GIL全局解释器的优缺点: 优点:
保证数据的安全
缺点:
单个进程下,开启多个线程,牺牲执行效率,无法实现并行,只能实现并发 - IO密集型:用多线程
- 计算密集型:用多进程
''' import time
from threading import Thread, Lock
lock = Lock() n = 100 def task():
lock.acquire()
global n
m = n
time.sleep(1)
n = m - 1
lock.release() if __name__ == '__main__':
list1 = [] for line in range(10):
t = Thread(target=task)
t.start()
list1.append(t) for t in list1:
t.join() print(n)
  • 查找资源
# 查文档,看是否能手动清理内存
# import gc # - 查看课外问题:
# - 国内: 开源中国、CSDN、cnblogs、https://www.v2ex.com/
# - 国外: Stack Overflow、github、谷歌

二、使用多线程提高效率

  • 实例
from threading import Thread
from multiprocessing import Process
import time '''
IO密集型下使用多线程
计算密集型下使用多进程 IO密集型任务,每个任务4s - 单核:
- 开启多线程节省资源 - 多核:
- 多线程:
- 开启4个子线程:16s - 多进程:
- 开启4个子进程:16s + 申请开启资源消耗的时间 计算密集型任务,每个任务4s
- 单核:
- 开启线程比进程节省资源 - 多核:
多线程:
- 开启4个子线程:16s 多进程:
- 开启多个进程:4s ''' # def task1():
# #计算1000000词的 += 1
# i = 10
# for line in range(1000000):
# i += 1
#
#
# def task2():
# time.sleep(2)
#
#
# if __name__ == '__main__':
#
# # 1、开启多进程
# # 测试计算密集型
# start_time = time.time()
# list1 = []
# for line in range(6):
# p = Process(target=task1)
# p.start()
# list1.append(p)
#
# for p in list1:
# p.join()
#
# end_time = time.time()
#
# #消耗时间
# print(f'多进程计算密集型消耗时间:{end_time - start_time}')
# #多进程密集型消耗时间:1.4906916618347168
#
# # 测试IO密集型
# start_time = time.time()
# list1 = []
# for line in range(6):
# p = Process(target=task2)
# p.start()
# list1.append(p)
#
# for p in list1:
# p.join()
#
# end_time = time.time()
#
# #消耗时间
# print(f'多进程IO型消耗时间:{end_time - start_time}')
#
#
#
#
# #2、开启多线程
# #测试计算密集型
# start_time = time.time()
# list1 = []
# for line in range(6):
# t = Thread(target=task1)
# t.start()
# list1.append(t)
#
# for t in list1:
# t.join()
#
# end_time = time.time()
# print(f'多线程计算密集型消耗时间:{end_time - start_time}')
# #多线程密集型消耗时间:0.41376233100891113
#
#
# #测试IO密集型
# start_time = time.time()
# list1 = []
# for line in range(6):
# t = Thread(target=task2)
# t.start()
# list1.append(t)
#
# for t in list1:
# t.join()
#
# end_time = time.time()
# print(f'多线程IO密集型消耗时间:{end_time - start_time}')
# # 计算密集型任务
def task1():
# 计算1000000次 += 1
i = 10
for line in range(10000000):
i += 1 # IO密集型任务
def task2():
time.sleep(3) if __name__ == '__main__':
# 1、测试多进程:
# 测试计算密集型
start_time = time.time()
list1 = []
for line in range(6):
p = Process(target=task1)
p.start()
list1.append(p) for p in list1:
p.join()
end_time = time.time()
# 消耗时间: 5.33872389793396
print(f'计算密集型消耗时间: {end_time - start_time}') # 测试IO密集型
start_time = time.time()
list1 = []
for line in range(6):
p = Process(target=task2)
p.start()
list1.append(p) for p in list1:
p.join()
end_time = time.time()
# 消耗时间: 4.517091751098633
print(f'IO密集型消耗时间: {end_time - start_time}') # 2、测试多线程:
# 测试计算密集型
start_time = time.time()
list1 = []
for line in range(6):
p = Thread(target=task1)
p.start()
list1.append(p) for p in list1:
p.join()
end_time = time.time()
# 消耗时间: 5.988943815231323
print(f'计算密集型消耗时间: {end_time - start_time}') # 测试IO密集型
start_time = time.time()
list1 = []
for line in range(6):
p = Thread(target=task2)
p.start()
list1.append(p) for p in list1:
p.join()
end_time = time.time()
# 消耗时间: 3.00256085395813
print(f'IO密集型消耗: {end_time - start_time}') 结论:
# 由1和3对比得:在计算密集型情况下使用多进程(多核的情况下多个CPU)
# 由2和3对比得:在IO密集型情况下使用多线程(多核的情况下多个CPU) # 都使用多线程(单核单个CPU)

三、协程

  • 演示
'''
1、什么是协程?
- 进程:资源单位
- 线程:执行单位
- 协程:单线程下实现并发 - 在IO密集型的情况下,使用协程能提高最高效率 注意;协程不是任何单位,只是一个程序员YY出来的东西 总结:多进程---> 多线程---> 让每一个线程都实现协程(单线程下实现并发) 协程的目的:
- 手动实现“遇到IO切换 + 保存状态” 去欺骗操作系统,让操作系统误以为没有IO操作,将CPU的执行权限给你
''' import time def task1():
time.sleep(1) def task2():
time.sleep(3) def task3():
time.sleep(5) def task4():
time.sleep(7) def task5():
time.sleep(9) #遇到IO切换(gevent) + 保存状态 from gevent import monkey #猴子补丁 monkey.patch_all() #监听所有的任务是否有IO操作
from gevent import spawn #spawn(任务) from gevent import joinall
import time def task1():
print('start from task1....')
time.sleep(1)
print('end from task1....') def task2():
print('start from task2....')
time.sleep(1)
print('end from task2....') def task3():
print('start from task3....')
time.sleep(1)
print('end from task3....') if __name__ == '__main__': start_time = time.time()
sp1 = spawn(task1)
sp2 = spawn(task2)
sp3 = spawn(task3) # sp1.start()
# sp2.start()
# sp3.start()
# sp1.join()
# sp2.join()
# sp3.join()
joinall([sp1, sp2, sp3]) #等同于上面六步 end_time = time.time() print(f'消耗时间:{end_time - start_time}') # start from task1....
# start from task2....
# start from task3....
# end from task1....
# end from task2....
# end from task3....
# 消耗时间:1.0085582733154297 ### 四、tcp服务端实现并发 - 代码 ```python
- client 文件
import socket client = socket.socket() client.connect(
('127.0.0.1', 9000)
) print('Client is run....')
while True:
msg = input('客户端>>:').encode('utf-8')
client.send(msg) data = client.recv(1024)
print(data) - sever 文件
import socket
from concurrent.futures import ThreadPoolExecutor server = socket.socket() server.bind(
('127.0.0.1', 9000)
) server.listen(5) # 1.封装成一个函数
def run(conn):
while True:
try:
data = conn.recv(1024)
if len(data) == 0:
break
print(data.decode('utf-8'))
conn.send('111'.encode('utf-8')) except Exception as e:
break conn.close() if __name__ == '__main__':
print('Server is run....')
pool = ThreadPoolExecutor(50)
while True:
conn, addr = server.accept()
print(addr)
pool.submit(run, conn)

GIL以及协程的更多相关文章

  1. Python 线程----线程方法,线程事件,线程队列,线程池,GIL锁,协程,Greenlet

    主要内容: 线程的一些其他方法 线程事件 线程队列 线程池 GIL锁 协程 Greenlet Gevent 一. 线程(threading)的一些其他方法 from threading import ...

  2. CSIC_716_20191209【并发编程---GIL和协程】

    GIL   Global Interpreter Lock 全局解释锁 GIL对含IO的任务来说,会出现不能保证数据安全的情况.如下: from threading import Thread fro ...

  3. Python复习笔记(八)迭代器和生成器和协程

    1. 迭代器 1.1 可迭代对象 判断xxx_obj是否可以迭代 在第1步成立的前提下,调用 iter 函数得到 xxx_obj 对象的 __iter__ 方法的返回值 __iter__ 方法的返回值 ...

  4. Day037--Python--线程的其他方法,GIL, 线程事件,队列,线程池,协程

    1. 线程的一些其他方法 threading.current_thread()  # 线程对象 threading.current_thread().getName()  # 线程名称 threadi ...

  5. day 35 协程与gil概念

    博客链接: http://www.cnblogs.com/linhaifeng/articles/7429894.html 今日概要: 1 生产者消费者模型(补充) 2 GIL(进程与线程的应用场景) ...

  6. GIL线程全局锁 协程

    GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务 ...

  7. GIL与线程、进程、协程

    GIL全局解释器锁: 1.相信大家都知道python代码是不能直接被机器cpu识别和执行的,它要经过python解释器(也就是我们执行时候的python3 name.py)被编译成机器语言,pytho ...

  8. GIL解释器,协程,gevent模块

    GIL解释器锁 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CP ...

  9. Python 进程线程协程 GIL 闭包 与高阶函数(五)

    Python 进程线程协程 GIL 闭包 与高阶函数(五) 1 GIL线程全局锁 ​ 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的 ...

随机推荐

  1. HashMap的常见问题

    关于HashMap的一些常见的问题,自己总结一下: 首选HashMap在jdk1.7和jdk1.8里面的实现是不同的,在jdk1.7中HashMap的底层实现是通过数组+链表的形式实现的,在jdk1. ...

  2. [Java并发] AQS抽象队列同步器源码解析--锁获取过程

    要深入了解java并发知识,AbstractQueuedSynchronizer(AQS)是必须要拿出来深入学习的,AQS可以说是贯穿了整个JUC并发包,例如ReentrantLock,CountDo ...

  3. 【Flutter】348- 写给前端工程师的 Flutter 教程

    点击上方"前端自习课"关注,学习起来~ | 导语 最爱折腾的就是前端工程师了,从 jQuery 折腾到 AngularJs,再折腾到 Vue.React.最爱跨屏的也是前端工程师, ...

  4. android之 xml文件一般用到的属性

    android:layout_above 将该控件的底部至于给定ID的控件之上android:layout_below 将该控件的顶部至于给定ID的控件之下android:layout_toLeftO ...

  5. PHP ftp获取目录内容为空

    使用PHP的ftp函数获取目录内容,ftp_nlist()和ftp_rawlist()返回都为空. 查了一圈资料找不到答案,然后用Python写了一个,一样的操作就可以获取目录内容. 抓包发现,Pyt ...

  6. Test 1022

    T1 AERODROM (二分答案 TimeLimit: 1000MS Memory Limit: 32768KB \(N\)个登机口,办理登机业务,第\(i\)个窗口的单位办理时间为\(T_i\), ...

  7. 《Java数据结构》树形结构

    树形结构是一层次的嵌套结构. 一个树形结构的外层和内层有相似的结构, 所以这种结构多可以递归的表示.经典数据结构中的各种树形图是一种典型的树形结构:一颗树可以简单的表示为根, 左子树, 右子树. 左子 ...

  8. 5. abp集成asp.net core

    一.前言 参照前篇<4. abp中的asp.net core模块剖析>,首先放张图,这也是asp.net core框架上MVC模块的扩展点 二.abp的mvc对象 AbpAspNetCor ...

  9. 升鲜宝V2.0_生鲜配送管理系统_杭州生鲜配送行业,升鲜宝使用教程 客户管理 第二章

    1.新增客户 (1)新增客户有两种方式,单个添加和批量添加,客户的结构可以是独立的,也可以是父子结构(比如杭州升鲜宝科技有限公司下有西湖区部门,滨江区部门,余杭区部门等多个分部,就可以建立父子结构,这 ...

  10. Java面试题_第一阶段(static、final、面向对象、多线程、集合、String、同步、接口、GC、JVM)

    1.1 简述static和final的用法? static:修饰属性,方法,代码块 (1)静态属性:也可叫类变量  类名.属性名  来访问 (共有的类变量与对象无关,只和类有关) 注意:类中的实例变量 ...