同步异步、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 ...
随机推荐
- Java之POI导出Excel(二):多个sheet
相信在大部分的web项目中都会有导出导入Excel的需求,之前我也写过一篇导出单个sheet工作表的文章,没看过的小伙伴可以去看哈,链接也给大家放出来了:导出单个sheet 但是在我们日常的工作中,需 ...
- Leetcode刷题笔记(双指针)
1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...
- BZOJ3732 Network(Kruskal重构树)
Kruskal重构树的模板题. 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N.图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: ...
- 程序员便于开发的一些工具、网站、App。
http://www.kancloud.cn 关于文档,各种技术,框架的学习指南,API文档搜索方便. https://leetcode.com/ 程序员刷题面试网站,无聊的时候可以做一做.
- 认识 Redis client-output-buffer-limit 参数与源码分析
概述 Redis 的 client-output-buffer-limit 可以用来强制断开无法足够快从 redis 服务器端读取数据的客户端.保护机制规则如下: [hard limit] 大小限制, ...
- [C#]SourceGenerator实战: 对任意对象使用await吧!!!
[C#]SourceGenerator实战: 对任意对象使用await吧!!! 前言 本文记录一次简单的 SourceGenerator 实战,最终实现可以在代码中 await 任意类型对象,仅供娱乐 ...
- 一天五道Java面试题----第十一天(分布式架构下,Session共享有什么方案--------->分布式事务解决方案)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.分布式架构下,Session共享有什么方案 2.简述你对RPC.RMI的理解 3.分布式id生成方案 4.分布式锁解决 ...
- Linux 文件操作接口
目录 Linux 文件操作接口 C语言文件操作接口 C语言文件描述 fopen() r模式打开文件 w模式打开文件 a模式打开文件 其他模式类似 fclose() fwrite() fread() 系 ...
- 【Kubernetes】K8s笔记(十一):Ingress 集群进出流量总管
目录 0. Ingress 解决了什么问题 1. Ingress Controller 2. 指定 Ingress Class 使用多个 Ingress Controller 3. 使用 YAML 描 ...
- html小总结(哪些可以直接设置高度和宽度)
(1)当然块级元素是可以直接设置高度和宽度的 块级元素:块级大多为结构性标记 div.h1~h6.ul.ol.dl.form.table.p.hr.pre.address.center.blockqu ...