同步异步、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
	以拷贝代码的形式创建进程
'''

image

方式一

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('主进程')

image

方式二

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('我是主进程的')

image

image

进程间数据隔离

同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况下)

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)

image

上面我们看到,在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())
        
 

image

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('我是主进程')

image

生产者 消费者模型

1.生产者

​ 负责生产数据的人

2.消费者

​ 负责处理数据的人

该模型除了有生产者和消费者之外还必须有消息队列(只有能够提供数据保存服务和提取服务的理论上都可以)

进程对象的多种方法

1.如何查看进程号
image

image

方式一
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 获取主进程的父进程

image

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)  # 获取当前进程的进程

image
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)  # 获取当前进程的进程

image

守护进程

主进程创建守护进程

  其一:守护进程会在主进程代码执行结束后就终止

  其二:守护进程内无法再开启子进程,否则抛出异常:

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()
   
"""
多进程操作数据很可能会造成数据错乱>>>:互斥锁
	互斥锁
		将并发变成串行 牺牲了效率但是保障了数据的安全
"""
posted @   小福福  阅读(96)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
  1. 1 原来你也在这儿 温余福
  2. 2 世间美好和你环环扣扣 温余福
  3. 3 随风起舞 温余福
  4. 4 罪恶都市 温余福
世间美好和你环环扣扣 - 温余福
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 尹初七

作曲 : 温余福

编曲 : 彭圣杰

偏偏秉烛夜游

偏偏秉烛夜游

午夜星辰 似奔走之友

爱你每个结痂伤口

酿成的陈年烈酒

入喉尚算可口

入喉尚算可口

怎么泪水 还偶尔失守

邀你细看心中缺口

裂缝中留存 温柔

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

让樱花偷偷 吻你额头

让世间美好 与你环环相扣

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

当樱花开的纷纷扬扬

当世间美好 与你环环相扣

特别鸣谢:槿葵,我们的海报制作妹妹。

原唱:柏松

吉他:柏松

和声:柏松

录音:柏松

混音:张强

点击右上角即可分享
微信分享提示