异步阻塞,Manager模块,线程
一、异步阻塞
1、并没有按照执行顺序等待结果
2、而是所有的任务都在异步执行着
3、但是我要的结果又不知道谁的结果先来,谁先结束我就先取谁的结果
很明显的异步,大家都相互执行着(异步过程),谁先结束我就先拿谁的结果,而我等待的过程就是一个阻塞过程,整体就是一个异步阻塞。
使用生产者消费者模型举例:
import requests
from multiprocessing import Process, Queue
url = [
'https://www.baidu.com',
'https://www.taobao.com',
'https://www.jd.com',
'https://i.cnblogs.com'
]
def producer(name, url, q): # 生产者负责爬取网页,获取状态码放进列队
ret = requests.get(url)
q.put((name, ret.status_code))
def consumer(q): # 消费者
while True:
conn = q.get()
if conn:
print(conn)
else:break
if __name__ == '__main__':
q = Queue()
p_list = []
for i in url:
p = Process(target=producer, args=(i, i, q))
p.start()
p_list.append(p)
Process(target=consumer, args=(q,)).start() # 输出
('https://www.jd.com', 200)
('https://www.baidu.com', 200)
('https://www.taobao.com', 200)
('https://i.cnblogs.com', 200)
二、Manager模块进程间数据共享(了解)
进程之间是可以实现数据共享的,通过Manager这个类就可以实现了,只不过呢实现这个数据共享的代价是非常大的,即需要对这个共享的数据进行加锁,又要去操作许多不必要的操作。
一般情况下我们不使用这种方法,使用进程的原因就是因为进程之间数据隔离,如果非要让大量数据共享,就证明这个场景不适合用进程去解决
from multiprocessing import Process, Manager, Lock
def change_dic(dic, lock):
with lock: # 使用数据共享需要加锁才能保证数据的安全,和抢票例子一样
dic['count'] -= 1
if __name__ == '__main__':
m = Manager()
lock = Lock()
dic = m.dict({'count': 100}) # 可以是字典,列表
p_l = []
for i in range(100):
p = Process(target=change_dic, args=(dic, lock))
p.start()
p_l.append(p)
for p in p_l: p.join()
print(dic) # 输出
{'count': 0}
三、线程
进程:数据隔离,资源分配的最小单位,可以利用多核,由操作系统调度,数据不安全,开启关闭切换时间开销大
进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是CPU的执行单位。
线程:数据共享,操作系统调度的最小单位,可以利用多核,由操作系统调度,数据不安全,开启关闭切换时间开销小
能被操作系统调度(给CPU执行)的最小单位,同一个进程中的多个线程同时能被CPU执行,
线程与进程的区别:
1、线程共享创建它的进程的地址空间;进程具有自己的地址空间。
2、线程可以直接访问其进程的数据;进程具有父进程数据的副本。
3、线程可以直接与进程中的其他线程通信;进程必须使用进程间通信与同级进程进行通信。
4、新线程很容易创建;新进程需要复制父进程。
5、线程可以对同一进程的线程使用相当大的控制权;进程只能控制子进程。
6、对主线程的更改可能会影响该进程对其他线程的行为;对父进程的修改不会影响子进程。
线程的特点:
1、轻型实体:线程中的实体基本不拥有系统资源。
2、独立调度和分派的基本单位:由于线程很轻,故线程的切换非常迅速且开销小(同一进程中的)。
3、共享进程资源:线程在同一进程中的各个线程,都可以共享该进程拥有的所有资源。
4、可并发执行:在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行
全局解释器锁 GIL (global interpreter lock)
在CPython中的多线程中,垃圾回收机制(gc)理解为相当于一个线程,它使用了引用计数 + 分代回收,来对变量中的引用计数为0的变量进行回收,但是如果在多线程中当CPU同时对多个线程的变量进行操作,gc 都要兼顾对每条线程的变量做引用计数,这样的话还是会造成和抢票例子一样的效果,为此诞生了一个全局解释器锁,它让每条线程中的变量要被CPU操作时,同时并且只有一条线程能被CPU操作。
全局解释器锁的出现主要是为了完成gc的回收机制,对不同线程的引用计数的变化记录更加精准
但是全局解释器锁导致了同一个进程中的多个线程只能有一个线程真正被CPU执行
节省的是io操作时间,而不是CPU计算的时间,因为CPU的计算速度非常快,大部分情况下,我们没有办法把一条进程中所有的io操作规避掉。
四、threading模块
thread模块提供了基本的线程和锁的支持,threading提供了更高级别、功能更强的线程管理的功能。
thread模块不支持守护线程,当主线进程退出时,所有的子线程不论他们是否还在工作,都会被强行退出。而threading模块支持守护线程。
线程的创建Threading. Thread类
multiprocessing模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性。
current_thread()获取当前所在的线程对象,current_thread(). ident 通过 ident 可以获取线程id
线程是不能从外部terminale
所有的子线程只能是自己执行完代码之后关闭
enumerate 列表,存储了所有活着的线程对象,包括主线程
active_count 数字,存储了所有活着的线程个数
from threading import Thread, current_thread, active_count, enumerate
import time
def func(i):
time.sleep(1)
print(f'这是线程func{i},线程id={current_thread().ident}')
t_list = []
for i in range(5):
t = Thread(target=func, args=(i,))
t.start()
t_list.append(t)
print(enumerate())
print(f'活着的线程个数{active_count()}')
for th in t_list:
th.join()
print('所有的线程都执行完了!')
# 输出
[<_MainThread(MainThread, started 8600)>, <Thread(Thread-1, started 18832)>,...]
活着的线程个数6
这是线程func3,线程id=3148
这是线程func1,线程id=2296
这是线程func0,线程id=18832
这是线程func2,线程id=18644
这是线程func4,线程id=12072
所有的线程都执行完了!
使用面向对象创建线程
from threading import Thread, current_thread
class MyThread(Thread):
def __init__(self,i):
self.i = i
super().__init__()
def run(self):
print(f'这是线程{self.i},线程号={current_thread().ident}')
t = MyThread(1)
t.start() # 开启线程,在线程中执行run方法。
# 输出
这是线程1,线程号=10160
线程之间的数据共享
修改成功说明进程的数据是共享给线程的。
from threading import Thread
count = 100
def func():
global count
count -= 1
t_list = []
for i in range(100):
t = Thread(target=func)
t.start()
t_list.append(t)
for th in t_list:
th.join()
print(f'所有的线程执行完了,count={count}')
# 输出
所有的线程执行完了,count=0
异步阻塞,Manager模块,线程的更多相关文章
- {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll
Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...
- 进程&线程 同步异步&阻塞非阻塞
2015-08-19 15:23:38 周三 线程 线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码 线程安全问题都是由全局变量及静态变量引起的 若每个线程中对 ...
- Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程
1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...
- GIL 线程池 进程池 同步 异步 阻塞 非阻塞
1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...
- python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)
9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...
- Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程
Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...
- Manager模块 队列 管道 进程池
Manager模块 作用: 多进程共享变量. Manager的字典类型: 如果value是简单类型,比如int,可以直接赋值给共享变量,并可以后续直接修改 如果value是复杂类型 ,比如list, ...
- 队列,管道,manager模块
###生产者消费者关系### 主要是解耦(高内聚,低耦合),借助队列来实现生产者消费者 模型 栈:先进后出(First In Last Out 简称:FILO) 队列:先进先出(First In Fi ...
- 同步与异步&阻塞与非阻塞
摘要 一直为同步异步,阻塞非阻塞概念所困扰,特定总结了下,原来是这么个意思 一直为同步异步,阻塞非阻塞概念所困扰,特定总结了下 一.同步与异步的区别 1.概念介绍 同步:所谓同步是一个服务的完成需要依 ...
随机推荐
- EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录
前言 本文主要是讲解EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录 注意拦截器只有EF Core3.0+ 支持,2.1请考虑上下文工厂的形式实现. 说点题外话.. 一晃又大半年没更新技 ...
- Get和Post区别(转载)
转载自:https://www.cnblogs.com/logsharing/p/8448446.html GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一 ...
- 2018ICPC南京Problem G. Pyramid
题意: 询问类似于这样的三角形中:里面正三角形的个数是多少. 思路:打表找了个规律发现就是C4n+3 1 //#include<bits/stdc++.h> 2 #include& ...
- Reverse 高校网络信息安全运维挑战赛
Reverse 高校网络信息安全运维挑战赛 1 signed int sub_403CC0() 2 { 3 unsigned int v0; // eax 4 int key_lens; // eax ...
- iNeuOS工业互联平台,生产过程业务联动控制
1.概述 工业物联网也好.工业互联网也好或是其他生产系统,反向控制始终无法回避.搞工业最直接.最体现效果的两个方面是采集各种数据和生产过程业务控制,所谓大数据预测和分析,那是仁者见仁.智者见智,下一篇 ...
- LevelDB 源码解析之 Arena
GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...
- 第14 章 : Kubernetes Service讲解
Kubernetes Service 本文将主要分享以下四方面的内容: 为什么需要 K8s service: K8s service 用例解读: K8s service 操作演示: K8s servi ...
- 结对编程_stage1
项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目-第一阶段 我在这个课程的目标是 从实践中学习软件工程相关知识(结构化分析和设计方法.敏捷开发方法. ...
- 13.Quick QML-RowLayout、ColumnLayout、GridLayout布局管理器介绍、并通过GridLayout设计的简易网站导航界面
上章我们学习了:12.Quick QML-QML 布局(Row.Column.Grid.Flow和嵌套布局) .Repeater对象,本章我们继续来学习布局管理器 1.RowLayout.Column ...
- JAVAEE_Servlet_08_HTTP状态码以及错误页面设置
HTTP协议状态码 * HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用, HTTP状态码共分为5种类型: - 1** 信息,服务器收到请求,需要请求者 ...