同步异步、mutiprocessing创建进程process模块及进程对象的多种方法、消息队列Queue
同步异步
用来表达任务的提交方式
同步:提交任务之后原地等待任务的返回结果 期间不做任何事
异步:提交任务之后不愿等待任务的返回结果 直接去做其他事 有结果自动通知
eg:
同步:客户端发送请求给服务端,在等待服务端响应的请求时,客户端不做其他的事情。当服务端做完了才返回到客户端。这样的话客户端需要一直等待
异步:当客户端发送给服务端请求时,在等待服务端响应的时候,客户端可以做其他的事情,这样节约了时间,提高了效率
阻塞与非阻塞
用来表达任务的执行状态
阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关 也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的角度来说的
阻塞:阻塞态
非阻塞:就绪态、运行态
综合使用
同步阻塞:效率最低 你一直在原地专心等待啥事也不干
异步阻塞:异步操作是可以被阻塞的 只不过他不是在处理消息时阻塞 而是在等待消息通知时被阻塞
同步非阻塞:需要在这两种不同的行为之间来回切换 效率低下
异步非阻塞:效率最高
总结:阻塞和非阻塞描述的是程序在等待调用结果(消息 返回值)时的状态;同步和异步描述的是消息通信的机制
创建进程的多种方式之multiprocess.process模块
'''
1.鼠标双击软件图标
2.python代码创建进程
'''
multiprocess.process模块
process模块是一个创建进程的模块
from multiprocessing import Process
import time
def task():
print('task is running')
time.sleep(3)
print('task is over')
p1 = Process(target=task)
p1.start()
print('主进程')
'''
在不同操作系统中穿创建进程底层原理不一样
windows
以导入模块的形式创建进程
linux/mac
以拷贝代码的形式创建进程
'''
方式一
from multiprocessing import Process
import time
def task(name):
print('task is running', name)
time.sleep(3)
print('task is over', name)
if __name__ == '__main__':
# p1 = Process(target=task, args=('jason',)) # 位置参数
p1 = Process(target=task, kwargs={'name': 'jason'}) # 关键字参数
p1.start() # 异步 告诉操作系统创建一个新的进程 并在该进程中执行task函数
print('主进程')
方式二
from multiprocessing import Process
import time
class MyProcess(Process):
def run(self):
print('run is running')
time.sleep(3)
print('run is over')
if __name__ == '__main__':
obj = MyProcess()
obj.start()
print('我是主进程的')
# 传参
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, name, age): # 传值需要从新重写双下init方法
super().__init__() # 这里init括号不传参是因为 父类init里面的形参全是默认参数 需注意super所放的位置
self.name = name # 这里的self是进程对象 给新产生的进程对象新增两个对象独有的属性name、age
self.age = age
# super().__init__()
def run(self):
print('run is running', self.name, self.age)
time.sleep(3)
print('run is over', self.name, self.age)
if __name__ == '__main__':
obj = MyProcess('jason', 123)
obj.start()
print('我是主进程的')
进程间数据隔离
同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况下)
from multiprocessing import Process
import time
money = 10000
def task():
global money
money = 888
print('子进程的task函数查看money', money)
if __name__ == '__main__':
p1 = Process(target=task)
p1.start()
time.sleep(3)
print(money)
上面我们看到,在windows中创建进程是相当于导模块的操作,因此可以看成子进程的代码相当于在另外一个py文件中执行,虽然用上了global改变全局变量,因为跟主进程不在一个文件,可以看成产生了数据隔离
进程的join方法
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
P = Process(target=task, args=('jason',))
P.start() # 异步
P.join() # 主进程代码等待子进程代码运行结束再执行
print('我是主进程的') # 这样主进程的永远都是最后打印
# 变形
from multiprocessing import Process
import time
def task(name, n):
print('%s is running' % name)
time.sleep(n)
print('%s is over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('jason1', 1))
p2 = Process(target=task, args=('jason2', 2))
p3 = Process(target=task, args=('jason3', 3))
start_time = time.time()
p1.start() # 主进程同时创建了3个子进程P1 P2 P3 在第一个P1进程执行时 时间为1秒 那么其他子进程P2 P3异步也执行了1秒 同理到在P2子进程时执行2秒 P3也执行了2秒了
# p1.join()
p2.start()
# p2.join()
p3.start()
# p3.join() # 按顺序的话就是一个个来轮流执行 时间6秒多
p1.join()
p2.join()
p3.join()
print(time.time() - start_time) # 3秒多
打印结果:
jason1 is running
jason2 is running
jason3 is running
jason1 is over
jason2 is over
jason3 is over
3.097902297973633
IPC机制
IPC:进程间通信
消息队列:储存数据的地方 所有人都可以存 也都可以取
from mutiprocessing import Queue
q = Queue(3) # 括号内可以指定存储数据的个数
q.put(999) # 往队列里存放数据
q.put(666)
q.put(888)
print(q.full()) # True 判断队列是否已满
print(q.get()) # 999 从消息队列中取数据 按照先进先出取值
print(q.empty()) # Flase 判断队列里是否为空
from multiprocessing import Process,Queue
def product(q):
q.put('子进程获取队列中的数据', q.get())
full() empty() 在多进程中都不能使用
from multiprocessing import Process, Queue
def product(q):
q.put('子进程p添加的数据')
def consumer(q):
print('子进程获取队列中的数据', q.get())
if __name__ == '__main__':
q = Queue()
# 主进程往队列中添加数据
# q.put('我是主进程添加的数据')
p1 = Process(target=consumer, args=(q,))
p2 = Process(target=product, args=(q,))
p1.start()
p2.start()
print('我是主进程')
生产者 消费者模型
1.生产者
负责生产数据的人
2.消费者
负责处理数据的人
该模型除了有生产者和消费者之外还必须有消息队列(只有能够提供数据保存服务和提取服务的理论上都可以)
进程对象的多种方法
1.如何查看进程号
方式一
from multiprocessing import Process, current_process
def task():
print(current_process())
print(current_process().pid) # 获取当前进程的进程
if __name__ == '__main__':
p = Process(target=task)
p.start()
print(current_process())
print(current_process().pid) # 获取当前进程的进程
方式二
from multiprocessing import Process
import os
def task():
print('我是子进程', os.getpid()) # 我是子进程 34604
if __name__ == '__main__':
p = Process(target=task)
p.start()
print('我是主进程', os.getpid()) # 我是主进程 40604
print('我是pycharm进程编号', os.getppid) # 我是pycharm进程编号 33528 获取主进程的父进程
2.终止进程
from multiprocessing import Process, current_process
import time
def task():
print('子进程',current_process().pid) # 获取当前进程的进程
if __name__ == '__main__':
p = Process(target=task)
p.start()
# time.sleep(0.1)
p.terminate() # 终止p子进程 也是异步操作
print('主进程', current_process().pid) # 获取当前进程的进程
3.判断进程是否存活
from multiprocessing import Process, current_process
import time
def task():
print('子进程',current_process().pid) # 获取当前进程的进程
if __name__ == '__main__':
p = Process(target=task)
p.start()
# p.terminate()
print(p.is_alive()) # 判断子进程是否存活
# time.sleep(0.1)
# p.terminate() # 终止p子进程 也是异步操作
print('主进程', current_process().pid) # 获取当前进程的进程
守护进程
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:
AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
守护进程会随着守护的进程结束而立刻结束
eg: 吴勇是张红的守护进程 一旦张红嗝屁了 吴勇立刻嗝屁
from multiprocessing import Process
import time
def task(name):
print('德邦总管:%s' % name)
time.sleep(3)
print('德邦总管:%s' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('大张红',))
p1.daemon = True
p1.start()
time.sleep(1)
print('恕瑞玛皇帝:小吴勇嗝屁了')
僵尸进程与孤儿进程
僵尸进程
进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来‘
比如进程号、进程执行时间、进程消耗功率等给父进程查看
ps:所有的进程都会变成僵尸进程
孤儿进程
子进程正常运行 父进程意外死亡 操作系统针对孤儿进程会派遣福利院管理
多进程数据错乱问题
模拟抢票软件
from multiprocessing import Process
import time
import json
import random
# 查票
def search(name):
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num')))
# 买票
def buy(name):
# 再次确认票
with open(r'data.json', 'r', encoding='utf8') as f:
data = json.load(f)
# 模拟网络延迟
time.sleep(random.randint(1, 3))
# 判断是否有票 有就买
if data.get('ticket_num') > 0:
data['ticket_num'] -= 1
with open(r'data.json', 'w', encoding='utf8') as f:
json.dump(data, f)
print('%s买票成功' % name)
else:
print('%s很倒霉 没有抢到票' % name)
def run(name):
search(name)
buy(name)
if __name__ == '__main__':
for i in range(10):
p = Process(target=run, args=('用户%s'%i, ))
p.start()
"""
多进程操作数据很可能会造成数据错乱>>>:互斥锁
互斥锁
将并发变成串行 牺牲了效率但是保障了数据的安全
"""
同步异步、mutiprocessing创建进程process模块及进程对象的多种方法、消息队列Queue的更多相关文章
- 第三十天- 进程 Process模块 空间隔离
1.进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体: ...
- python中datetime模块中datetime对象的使用方法
本文只讲述datetime模块中datetime对象的一些常用的方法,如果读者需要更多datetime模块的信息,请查阅此文档. datetime模块的对象有如下: timedelta date da ...
- GCD,用同步/异步函数,创建并发/串行队列
队列 第一个参数:C语言字符串,标签 第二个参数: DISPATCH_QUEUE_CONCURRENT:并发队列 DISPATCH_QUEUE_SERIAL:串行队列 dispatch_queue_ ...
- 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02
百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...
- C# ABP - 创建自己的模块
本篇文章介绍怎么创建自己的模块,并且使用依赖注入方法进行模块间的无缝结合. 我们创建一下自己的一个会员模块,针对不同的系统都可以用.你们可以看看我是怎么做的,或者从中得到启发. 目录 1.开始创建项目 ...
- python---基础知识回顾(十)进程和线程(进程)
前戏:进程和线程的概念 若是学过linux下的进程,线程,信号...会有更加深刻的了解.所以推荐去学习下,包括网络编程都可以去了解,尤其是对select,poll,epoll都会有更多的认识. 进程就 ...
- 8.7 进程间的通讯:管道、消息队列、共享内存、信号量、信号、Socket
进程间的通讯 进程间为什么需要通讯? 共享数据.数据传输.消息通知.进程控制 进程间的通讯有哪些类型? 首先,联系前面讲过的知识,进程之间的用户地址空间是相互独立的,不能进行互相访问,但是,内核空间却 ...
- linux 进程学习笔记-消息队列messagequeue
可以想象,如果两个进程都可以访问同一个队列:其中一个进程(sender)向其中写入结构化数据,另外一个进程(receiver)再从其中把结构化的数据读取出来.那么这两个进程就是在利用这个队列进行通信了 ...
- day43-python消息队列二-queue模块
Python提供了Queue模块来专门实现消息队列Queue对象 Queue对象实现一个fifo队列(其他的还有lifo.priority队列,这里不再介绍).queue只有maxsize一个构造参数 ...
- {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll
Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...
随机推荐
- Git Review + Gerrit 安装及使用完成 Code-Review
转载自:https://cloud.tencent.com/developer/article/1010615 1.Code Review 介绍 Code Review 代码评审是指在软件开发过程中, ...
- 11_Swagger
一. 引言 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务. 总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法.参数和模 ...
- 密码学奇妙之旅、03 HMAC单向散列消息认证码、Golang代码
HMAC 单向散列消息认证码 消息认证码MAC是用于确认完整性并进行认证的技术,消息认证码的输入包括任意长度的消息和一个发送者和接收者之间共享的密钥(可能还需要共享盐值). HMAC是使用单向散列函数 ...
- Java实现6种常见排序
1.冒泡排序(Bubble Sort) 第0轮 3 1 4 1 5 9 2 6 5 3 5 8 9 第1轮 1 3 1 4 5 2 6 5 3 5 8 9 9 第2轮 1 1 3 4 2 5 5 3 ...
- SpringBoot实战派读书笔记---响应式编程
1.什么是WebFlux? WebFlux不需要Servlet API,在完全异步且无阻塞,并通过Reactor项目实现了Reactor Streams规范. WebFlux可以在资源有限的情况下提高 ...
- 谣言检测(DUCK)《DUCK: Rumour Detection on Social Media by Modelling User and Comment Propagation Networks》
论文信息 论文标题:DUCK: Rumour Detection on Social Media by Modelling User and Comment Propagation Networks论 ...
- 6.pygame-搭建主程序
职责明确 新建plane_main.py 封装主游戏类 创建游戏对象 启动游戏 新建plane_sprites.py 封装游戏中所有需要使用的精灵子类 提供游戏的相关工具 #plane_sprit ...
- 17_Vue列表过滤_js模糊查询
列表过滤 需求分析 这里呢有张列表,假设这个列表有一百多条数据 当我在这个 搜索框当中 搜索 单个关键字的时候 (冬,周,伦),它能把带了这几个关键字的信息都给我罗列出来 === 跟数据库的 模糊查询 ...
- 栈溢出漏洞利用流程——以syncbrs为例
0x1 缓冲区溢出漏洞攻击简介 缓冲区溢出攻击是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序的堆栈,使程序转而执行其他指令,以达到攻击 ...
- 现代 CSS 指南 -- at-rule 规则扫盲
大部分同学都用过 CSS 的屏幕宽度媒体查询,像是这样: @media screen and (min-width: 900px) { div { padding: 1rem 3rem; } } 这里 ...