同步异步、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 ...
随机推荐
- 使用cnpm创建vue项目(含离线安装)
# 全局安装淘宝cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org #升级 npm cnpm install npm ...
- Spring笔记三
Spring-03 1. AOP 1.1 概念 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程.他是一种可以在不修改原来的核心代码的情况下给程序动态统一进 ...
- 糟了,线上服务出现OOM了
前言 前一段时间,公司同事的一个线上服务OOM的问题,我觉得挺有意思的,在这里跟大家一起分享一下. 我当时其实也参与了一部分问题的定位. 1 案发现场 他们有个mq消费者服务,在某一天下午,出现OOM ...
- 微软出品自动化神器【Playwright+Java】系列(五) 之 常见点击事件操作
写在前面 明天就是周五了,这周有那么一两天心情特别不好,真的是做什么都没兴致,所以导致整个人都很丧,什么都不想做. 本打算周一就更新这篇文章的,但由于公司一直加班,每天到家很晚,都是挤时间去学,理解后 ...
- Java学习之路:运算符
2022-10-10 10:34:08 1 运算符 算术运算符:+, -, *, /, %, ++, -- 赋值运算符:= 关系运算符:>, <, >=, <=, ==, != ...
- Spring的同一个服务为什么会加载多次?
问题现象 最近在本地调试公司的一个Web项目时,无意中发现日志中出现了两次同一个服务的init记录,项目都是基于Spring来搭建的,按理说服务都是单例的,应该只有一次服务加载日志才对,本着对工作认真 ...
- 4.RabbitMQ系列之发布/订阅模式
我们把一个消息转发给多个消费者,这种模式称之为发布-订阅模式 1.交换器(Exchange) RabbitMq消息模式的核心思想是:一个生产者并不会直接往一个队列中发送消息,事实上,生产者根本不知道它 ...
- 【多线程那些事儿】如何使用C++写一个线程安全的单例模式?
如何写一个线程安全的单例模式? 单例模式的简单实现 单例模式大概是流传最为广泛的设计模式之一了.一份简单的实现代码大概是下面这个样子的: class singleton { public: stati ...
- 齐博x1标签之异步加载标签数据
为什么要异步加载标签?他有什么好处 如果一个页面的标签太多,又或者是页面中某一个标签调用数据太慢的话,就会拖慢整个页面的打开,非常影响用户体验.这个时候,用异步加载的话,就可以一块一块的显示,用户体验 ...
- [Oracle]复习笔记-SQL部分内容
Oracle笔记--SQL部分 整体框架 语句的执行顺序:from →where →group by→having→select→order by select * from * where * gr ...