异步阻塞,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.概念介绍 同步:所谓同步是一个服务的完成需要依 ...
随机推荐
- 通俗地理解面向服务的架构(SOA)以及微服务之间的关系
SOA是一种软件的应用架构方法,它基于面向对象,但又不是面向对象,整体上是面向服务的架构.SOA由精确的服务定义.松散的构件服务组成,以及业务流程调用等多个方面形成的一整套架构方法. 这话是不是听起来 ...
- 你说,怎么把Bean塞到Spring容器?
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 小傅哥,你是怎么学习的? 有很多初学编程或者码了几年CRUD砖的小伙伴问我,该怎么学 ...
- java面试-生产环境服务器变慢,谈谈你的诊断思路
1.uptime:查询linux系统负载 11:16:16 系统当前时间 up 64 days, 19:23 从上次启动开始系统运行的时间3 users 连接数量,同一用户多个连接的时候算多个load ...
- Java(195-214)【final、权限、内部类】
1.final关键字的概念与四种方法 今天是基础学习的最后一天!~ 2.final关键字用来修饰一个类 3.final关键字来修饰成员方法 4.final用于修饰局部变量 package cn.itc ...
- k8s kubernetes给node节点添加标签和删除node节点标签
node节点IP 192.168.1.205 给节点添加标签的命令 添加label语法 kubectl label nodes <node-name> <label-key>= ...
- KMP算法:next和nextval值计算
KMP算法的next和nextval值计算 先看看next数据值的求解方法 例:下标从1开始(若题中给定下标为0开始,把所有值-1即可) next数组的求解方法:根据前一个字符next,一直循环找到第 ...
- Leecode第二题:两数相加
Leecode2 先看题目 : 给你两个 非空 的链表,表示两个非负的整数.它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字. 请你将两个数相加,并以相同形式返回一个表示和的 ...
- nginx下强制跳转到www域名
跳转www #先监听 exp.com域名,然后转发到www下面 server { listen 80; server_name exp.com; rewrite ^(.*) $scheme://www ...
- 从苏宁电器到卡巴斯基第10篇:我在苏宁电器当营业员 II
之所以是主推,其实是有原因的 据我所知,尽管诺基亚卖的很好,但是他们的厂促的待遇却很一般,估计也就一千多两千的样子,撑死两千多.但是呢,记得当时我们的卖场里面还有联想手机,别看卖得相当次,但是他们的厂 ...
- Tomcat容器、JSP和Servlet
目录 JSP Tomcat.JSP和Servlet JSP JSP全名为Java Server Pages,其根本是一个简化的Servlet设计.JSP技术有点类似ASP技术,它是在传统的HTML网页 ...