同步与异步
用来表达任务的提交方式
同步
提交完任务之后原地等待任务的返回结果,期间不做任何事情
异步
提交完任务之后不原地等待任务的返回结果,直接去做其他事有结果自动通知
阻塞与非阻塞
用来表达任务的执行状态
阻塞
阻塞态
非阻塞
就绪态或者运行态
综合使用
同步阻塞 '效率最低'
同步非阻塞
异步阻塞
异步非阻塞 '效率最高'
创建进程的多种方式
"""
1.鼠标双击软件图片运行
2.python代码创建进程
"""
"""
在不同的操作系统中创建进程底层原理不一样
windows
以导入模块的形式创建进程
linux/mac
以拷贝代码的形式创建进程
"""
创建子进程方式1:
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.start()
task('tom')
print('主')
创建子进程方式2:
import time
from multiprocessing import Process
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(3)
print('run is over', self.name, self.age)
if __name__ == '__main__':
obj = MyProcess('jason', 18)
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(3)
print(money)
进程的join方法
from multiprocessing import Process
import time
def task(name, n):
print('%s is running' % name)
time.sleep(n)
print('%s in over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('jason', 5))
p2 = Process(target=task, args=('jason', 6))
p3 = Process(target=task, args=('jason', 8))
star_time = time.time()
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
print(time.time() - star_time)
"""由于start是异步,所以3个子进程会同时开始执行,当p1.join等待p1子
进程的时候,也是相当于在等待p2,p3子进程"""
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_nowait())
"""
full() empty() 在多进程中都不能使用!!!
"""
子进程在消息队列中添加消息:
from multiprocessing import Queue, Process
def product(q):
q.put('子进程p添加的数据')
def consumer(q):
print('子进程获取队列中的数据', q.get())
if __name__ == '__main__':
q = Queue()
p1 = Process(target=consumer, args=(q,))
p2 = Process(target=product, args=(q,))
p1.start()
p2.start()
print('主')
生产者消费者模型
"""回想爬虫"""
生产者
负责产生数据的'人'
消费者
负责处理数据的'人'
该模型除了有生产者和消费者之外还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以)
进程对象的多种方法
1.如何查看进程号
from multiprocessing import Process, current_process
current_process()
current_process().pid
import os
os.getpid()
os.getppid()
2.终止进程
p1.terminate()
ps:计算机操作系统都有对应的命令可以直接杀死进程
3.判断进程是否存货
p1.is_alive()
4.start()
5.join()
守护进程
守护进程会随着守护的进程结束而立刻结束
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=('jason',))
p1.daemon = True
p1.start()
time.sleep(1)
print('主进程结束')
"""德玛西亚:jason
主进程结束
子进程的另一个打印操作未执行,因为主进程结束了,所以作为守护进程的子进程也直接结束
"""
僵尸进程与孤儿进程
僵尸进程
进程执行完毕后并不会立刻销毁所有的数据,会有一些信息短暂保留下来
比如:进程号、进程执行时间、进程消耗功率等给父进程查看
ps:所有的进程都会变成僵尸进程
孤儿进程
子进程正常运行,父进程意外死亡,操作系统针对孤儿进程会派遣福利院管理
多进程数据错乱问题
模拟抢票软件
from multiprocessing import Process
import time
import json
import random
def search(name):
with open(r'data.json', 'r', encoding='utf8') as f:
date = json.load(f)
print('%s在查票 当前余票为%s' % (name, date.get('ticket_num')))
def buy(name):
with open(r'data.json', 'r', encoding='utf8') as f:
date = json.load(f)
time.sleep((random.randint(1, 3)))
if date.get('ticket_num') > 0:
date['ticket_num'] -= 1
with open(r'data.json', 'w', encoding='utf8') as f:
json.dump(date, 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()
"""
多进程操作数据很可能会造成数据错乱>>>:互斥锁
互斥锁
将并发变成串行 牺牲了效率但是保障了数据的安全
"""
```python
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
client.send(b'hello word')
date = client.recv(1024)
print(date)
服务端代码
import socket
from multiprocessing import Process
def get_server():
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
return server
def get_talk(sock):
while True:
date = sock.recv(1024)
print(date.decode('utf8'))
sock.send(date.upper())
if __name__ == '__main__':
server = get_server()
while True:
sock, addr = server.accept()
p = Process(target=get_talk, args=(sock,))
p.start()
互斥锁代码实操
锁:建议只加载操作数据的部分 否则整个程序的效率会极低
from multiprocessing import Process, Lock
import time
import json
import random
def search(name):
with open(r'date.json', 'r', encoding='utf8') as f:
date = json.load(f)
print(f'{name}查看余票,目前余票剩余{date.get("ticket_num")}')
def buy(name):
with open(r'date.json', 'r', encoding='utf8') as f:
date = json.load(f)
time.sleep(random.randint(1, 3))
if date.get('ticket_num') > 0:
date['ticket_num'] -= 1
with open(r'date.json', 'w', encoding='utf8') as f1:
json.dump(date, f1)
print(f'{name}买票成功')
else:
print(f'{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=(f'用户编号{i}', mutex))
p.start()
"""
锁有很多种 但是作用都一样
行锁 表锁
"""
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)