python31 网络并发编程方法
同步与异步
用来表达任务的提交方式
同步
提交完任务之后原地等待任务的返回结果 期间不做任何事
异步
提交完任务之后不原地等待任务的返回结果 直接去做其他事 有结果自动通知
阻塞与非阻塞
用来表达任务的执行状态
阻塞
阻塞态
非阻塞
就绪态、运行态
总结
同步阻塞
同步非阻塞
异步阻塞
异步非阻塞(******)
效率最高
同步、异步,与阻塞、非阻塞不相关。
同步、异步强调的是结果。
阻塞和非阻塞强调的是时间,是否等待。
同步与异步区别在于:调用者是否得到了想要的最终结果。
同步就是一直要执行到返回最终结果。
异步就是直接返回了,但是返回的不是最终的结果,调用者不能通过这种调用得到结果,还要通过被调用者,使用其他方式通知调用者,来取回最终结果。
阻塞与非阻塞的区别在于,调用者是否还能干其他的事情。
阻塞,调用者只能干等。
非阻塞,调用者可以先忙一会别的,不用一直等。
联系:
同步阻塞:调用者阻塞,直到等到拿到最终结果。(打饭模型,什么事情也不敢,就等着打饭,打饭是结果,什么也不干,一直在等着,同步加阻塞)
同步非阻塞:(等着打饭,但是可以玩会手机,看看电视,打饭是结果,但是不用一直在等着)
异步阻塞:(我要打饭,你说等着较好,并没有返回饭给我,我啥事不干,就干等着饭好了叫我)
异步非阻塞:回调的话。(我要打饭,你说等较好,并没有返回饭给我,可以在旁边看看电视,玩玩手机,饭好了叫我)
同步IO、异步IO、IO多路复用
IO模型:
IO分为两个阶段。
1)数据准备阶段。
2)内核空间复制回用户进程缓冲区阶段。
发生IO的时候:
1、内核从输入设备读、写数据(淘米,把米放锅里煮饭)
2、进程从内核复制数据(盛饭,从内核这个锅把饭装到碗里面来)
创建进程的两种方式
"""
1.鼠标双击软件图标
2.python代码创建进程
"""
1、利用函数创建
from multiprocessing import Process
import time
def task(name):
print('task is running',name)
time.sleep(1)
print('task is over', name)
if __name__ == '__main__':
p1 = Process(target=task,args=('jason',)) # 位置参数
# p1 = Process(target=task,kwargs={'name':'jason123'}) # 关键字参数
p1.start() # 异步 告诉操作系统创建一个新的进程 并在该进程中执行task函数
# task() # 同步
print('主程序')
"""
在不同的操作系统中 创建进程底层原理不一样
windows
以导入模块的形式创建进程
linux/mac
以拷贝代码的形式创建进程
"""
2、利用类创建
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name,age):
super().__init__()
self.name = name
self.age = age
def run(self):
print('run is running',self.name, self.age)
time.sleep(2)
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 = 1000
def task():
global money
money = 666
print('子进程的task函数产看money', money)
if __name__ == '__main__':
p1 = Process(target=task)
p1.start() # 创建子进程
time.sleep(2) # 主进程代码等待2秒
print(money) # 主进程代码打印money
进程的join方法
主进程代码等待子进程代码执行完毕 再执行主进程代码
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))
# p1.start() # 异步
# p1.join()
# print('主程序')
stat_time = time.time()
p1.start()
p1.join()
p2.start()
p2.join()
p3.start()
p3.join()
# p1.join()
# p2.join()
# p3.join()
print(time.time() - stat_time) # 6秒多
IPC机制
IPC:进程间通信
消息队列:存储数据的地方 所有人都可以存 也都可以取
from multiprocessing import Queue
q = Queue(3) # 括号内可以指定存储数据的个数
# 往消息队列中存放数据
q.put(111)
print(q.full()) # 判断消息队列是否已满
q.put(222)
q.put(333)
print(q.full()) # 判断消息队列是否已满
# 从消息队列中取数据
print(q.get())
print(q.get())
print(q.empty()) # 判断队列是否为空
print(q.get())
print(q.empty()) # 判断队列是否为空
print(q.get()) # 取数据 无数据会原地等待
# print(q.get_nowait()) # 也是取数据 但是如果队列里面没有数据会报错
'''full() empty() 在多进程中都不能使用!!!!'''
from multiprocessing import Process, Queue
def producer(q):
q.put('子进程q添加的数据')
def consumer(q):
print('子进程获取队列中的数据', q.get())
if __name__ == '__main__':
q = Queue()
# 主进程往队列中添加数据
q.put('我是主进程添加的数据')
p1 = Process(target=consumer, args=(q,))
# p2 = Process(target=producer, args=(q,))
p1.start()
# p2.start()
print('主进程')
生产者消费者模型
生成者
负责产生数据的'人'
消费者
负责处理数据的'人'
该模型除了有生产者和消费者之外还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以)
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
进程对象的多种方法
1.如何查看进程号
from multiprocessing import Process,current_process
current_process()
print(current_process().pid)
import os
print(os.getpid())
print(os.getppid())
2.终止进程
p1.terminate()
ps:计算机操作系统都有对应的命令可以直接杀死进程
3.判断进程是否存活
p1.is_alive()
5.start() 创建进程
6.join() 阻塞等待进程
守护进程
守护进程会随着守护的进程结束而立刻结束
eg: A是B的守护进程 一旦B嗝屁了 A立刻嗝屁
from multiprocessing import Process
import time
def task(name):
print('德邦总管: %s' % name)
time.sleep(2)
print('德邦总管: %s' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('B',))
p1.daemon = True
p1.start()
time.sleep(1)
print('恕瑞玛皇帝: A嗝屁了')
僵尸进程与孤儿进程
僵尸进程
进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来
比如进程号、进程执行时间、进程消耗功率等给父进程查看
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.randrange(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(1,11):
p = Process(target=run, args=('用户%s' % i,))
p.start()
"""
多进程操作数据很肯会造成数据错乱>>>:互斥锁
互斥锁
将并发变成串行 牺牲了效率但是保障了数据的安全
"""
# 加锁之后的代码
from multiprocessing import Process,Lock
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:
with open(r'data.json', 'w',encoding='utf8')as f:
data['ticket_num'] -= 1
json.dump(data,f)
print('%s 买票成功' % name)
else:
print('%s 买票失败 非常可乐 没车回去了'% name)
def run(name,mutex):
search(name)
mutex.acquire() # 抢锁
buy(name)
mutex.release() # 释放锁
if __name__ == '__main__':
mutex = Lock() # 产生一把锁
for i in range(10):
p = Process(target=run, args=('用户%s号' % i,mutex))
p.start()
"""
锁有很多种 但是作用都一样
行锁 表锁。。。。
"""
python31 网络并发编程方法的更多相关文章
- 2、网络并发编程--套接字编程、黏包问题、struct模块、制作简易报头、上传文件数据
昨日内容回顾 面向对象复习(json序列化类) 对象.类.父类的概念 三大特性:封装 继承 多态 双下开头的方法(达到某个条件自动触发) __init__:对象实例化自动触发 __str__:对象执行 ...
- 1、网络并发编程--简介、软件开发架构、OSI七层协议
python复习 变量与常量 基本数据类型 内置方法 字符编码.文件操作 函数 函数参数.闭包函数.装饰器 面向对象 封装.继承.多态 """ 什么是对象 数据与功能的结 ...
- 3、网络并发编程--udp代码、操作系统发展史、多道技术、进程理论
昨日内容回顾 socket基本使用 # 内置的模块 import socket s = socket.socket() # 默认是TCP协议 也可以切换为UDP协议 s.bind((ip,port)) ...
- python之路32 网络并发线程方法 线程池 协程
多进程实现TCP服务端并发 服务端: import socket from multiprocessing import Process def get_server(): server = sock ...
- 4、网络并发编程--僵尸进程、孤儿进程、守护进程、互斥锁、消息队列、IPC机制、生产者消费者模型、线程理论与实操
昨日内容回顾 操作系统发展史 1.穿孔卡片 CPU利用率极低 2.联机批处理系统 CPU效率有所提升 3.脱机批处理系统 CPU效率极大提升(现代计算机雏形) 多道技术(单核CPU) 串行:多个任务依 ...
- 【转】高性能网络编程5--IO复用与并发编程
对于服务器的并发处理能力,我们需要的是:每一毫秒服务器都能及时处理这一毫秒内收到的数百个不同TCP连接上的报文,与此同时,可能服务器上还有数以十万计的最近几秒没有收发任何报文的相对不活跃连接.同时处理 ...
- 03并发编程(多道技术+进程理论+进程join方法)
目录 03 并发编程 03 并发编程
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之三unlock方法分析
前篇博客LZ已经分析了ReentrantLock的lock()实现过程,我们了解到lock实现机制有公平锁和非公平锁,两者的主要区别在于公平锁要按照CLH队列等待获取锁,而非公平锁无视CLH队列直接获 ...
- Java并发编程(一) 两种实现多线程的方法(Thread,Runnable)
Java中实现多线程的方法有两种: 继承Thread类和实现Runnable方法,并重写Run方法,然后调用start()方法启动线程.使用Runnable会比Thread要好很多,主要是以下三个原因 ...
随机推荐
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(28)-Fiddler如何抓取Android7.0以上的Https包-下篇
1.简介 虽然依旧能抓到大部分Android APP的HTTP/HTTPS包,但是别高兴的太早,有的APP为了防抓包,还做了很多操作:① 二次加密有的APP,在涉及到关键数据通信时,会将正文二次加密后 ...
- MySQL安装卸载、idea中Database的使用、常用的sql语句
MySQL安装卸载 MySQL安装 在下面的资源链接中下载MySQL软件压缩包(绿色版),这个版本是MySQL5.7.29的,本教程也只适用于这个绿色版的,如果下载的是安装包那就可能有些地方不一样了, ...
- Vue学习之--------计算属性(2022/7/9)
文章目录 1.计算属性 1.1 计算属性实现 1.1.1 基础知识 1.1.2 代码实例 1.1.3 测试效果 1.2 计算属性简写 1.2.1 简写代码 1.3 使用插值语法实现 1.3.1 代码实 ...
- 成功解决:Can‘t find Python executable “python“, you can set the PYTHON env variable.
今天跑公司新项目的时候.运行前端vue.报了一个关于python的错误.就离谱 1.问题报错全部代码 actual version of core-js. npm ERR! code 1 npm ER ...
- 齐博x1直播神器聊天小插件
下载地址如下:https://down.php168.com/livemsg.rar 本插件由论坛网友笨熊提供 非常感谢他给大家提供那么一个非常好用的直播必备神器. 如下图所示,大家在直播的时候,这个 ...
- 学习ASP.NET Core Blazor编程系列九——服务器端校验
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- 有依赖的背包问题(Acwing 10)
1 # include<iostream> 2 # include<cstring> 3 # include<algorithm> 4 using namespac ...
- 怎么实现无痛刷新token
最近遇到这个需求,前端登录后,后端返回 access_token 和 refresh_token ,当token 过期时用旧的 refresh_token 去获取新的token,前端要不痛去刷新to ...
- jmeter接口自动化-通过csv文件读取用例并执行测试
最近在公司测试中经常使用jmeter这个工具进行接口自动化,简单记录下~ 一.在csv文件中编写好用例 首先在csv文件首行填写相关参数(可根据具体情况而定)并编写测试用例.脚本可通过优先级参数控制执 ...
- 嵌入式-C语言基础:数组作为参数传递需要注意的问题
#include <stdio.h> void printData(int data) { printf("%d\n",data); } //形参中不存在数组的概念,即 ...