同步异步

用来表达任务的提交方式

同步:提交任务之后原地等待任务的返回结果 期间不做任何事

异步:提交任务之后不愿等待任务的返回结果 直接去做其他事 有结果自动通知

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的更多相关文章

  1. 第三十天- 进程 Process模块 空间隔离

    1.进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体: ...

  2. python中datetime模块中datetime对象的使用方法

    本文只讲述datetime模块中datetime对象的一些常用的方法,如果读者需要更多datetime模块的信息,请查阅此文档. datetime模块的对象有如下: timedelta date da ...

  3. GCD,用同步/异步函数,创建并发/串行队列

    队列  第一个参数:C语言字符串,标签 第二个参数: DISPATCH_QUEUE_CONCURRENT:并发队列 DISPATCH_QUEUE_SERIAL:串行队列 dispatch_queue_ ...

  4. 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02

    百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...

  5. C# ABP - 创建自己的模块

    本篇文章介绍怎么创建自己的模块,并且使用依赖注入方法进行模块间的无缝结合. 我们创建一下自己的一个会员模块,针对不同的系统都可以用.你们可以看看我是怎么做的,或者从中得到启发. 目录 1.开始创建项目 ...

  6. python---基础知识回顾(十)进程和线程(进程)

    前戏:进程和线程的概念 若是学过linux下的进程,线程,信号...会有更加深刻的了解.所以推荐去学习下,包括网络编程都可以去了解,尤其是对select,poll,epoll都会有更多的认识. 进程就 ...

  7. 8.7 进程间的通讯:管道、消息队列、共享内存、信号量、信号、Socket

    进程间的通讯 进程间为什么需要通讯? 共享数据.数据传输.消息通知.进程控制 进程间的通讯有哪些类型? 首先,联系前面讲过的知识,进程之间的用户地址空间是相互独立的,不能进行互相访问,但是,内核空间却 ...

  8. linux 进程学习笔记-消息队列messagequeue

    可以想象,如果两个进程都可以访问同一个队列:其中一个进程(sender)向其中写入结构化数据,另外一个进程(receiver)再从其中把结构化的数据读取出来.那么这两个进程就是在利用这个队列进行通信了 ...

  9. day43-python消息队列二-queue模块

    Python提供了Queue模块来专门实现消息队列Queue对象 Queue对象实现一个fifo队列(其他的还有lifo.priority队列,这里不再介绍).queue只有maxsize一个构造参数 ...

  10. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

随机推荐

  1. day42-反射01

    Java反射01 1.反射(reflection)机制 1.1反射机制问题 一个需求引出反射 请看下面问题: 根据配置文件 re.properties 指定信息,创建Cat对象并调用方法hi clas ...

  2. [基础] BS/CS 区别 Http/Https 区别 中间件请求

    BS和CS的区别:   1.BS结构:Browser-Server-从浏览器到服务器,浏览器打开的所有内容都属于BS(三大主流浏览器Safari.Chrome和Firefo)   2.CS结构:Cli ...

  3. Seal-Report: 开放式数据库报表工具

    Seal Report是.Net的一个基于Apache 2.0 开源工具,完全用C# 语言编写,最新的6.6 版本采用.NET 6,github: https://github.com/ariacom ...

  4. SpringBoot实战派读书笔记---响应式编程

    1.什么是WebFlux? WebFlux不需要Servlet API,在完全异步且无阻塞,并通过Reactor项目实现了Reactor Streams规范. WebFlux可以在资源有限的情况下提高 ...

  5. AgileBoot - 手把手一步一步带你Run起全栈项目(SpringBoot+Vue3)

    AgileBoot是笔者在业余时间基于ruoyi改造优化的前后端全栈项目. 关于AgileBoot的详细介绍:https://www.cnblogs.com/valarchie/p/16777336. ...

  6. day46-JDBC和连接池02

    JDBC和连接池02 3.ResultSet[结果集] 基本介绍 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成 ResultSet对象保持一个光标指向其当前的数据行,最初,光标位于第一行 ...

  7. Python解决千年虫问题

    #避免千年虫(日期bug)问题 千年虫:部分计算机程序使用年份后两位作为记录年份,当日期跳转到00时候,默认会解析为1900,造成系统紊乱 lst=[45,89,1998,00,75,33,1968, ...

  8. 使用request对象进行简单的注册以及信息显示

    Request内置对象的使用 概述:request对象主要用于接收客户端发送的请求信息,客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应.封装了用户提交的信息.在 ...

  9. Django之同时新增数据到两个数据库表与同时返回两个表的数据(插拔式)

    models:比如有以下三个模型 from django.db import models """ 基类,其他类继承即可获得对应的字段 """ ...

  10. 基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

    在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件 ...