并发编程 2 进程

同步与异步

# 用来表达任务的提交方式
同步 : 提交完任务之后原地等待任务的返回结果,期间不做任何事
异步 : 提交完任务之后不愿地等待任务的返回结果,直接去做其他事,有结果自动通知.
异步非阻塞 (
效率最高

创建进程的多种方式

复制代码
# 1.鼠标双击软件图标
# 2.python代码创建进程
"""
在不同的操作系统中创建进程底层原理不一样
    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':'jason123'})  # 关键字参数
     p1.start()  # 异步 告诉操作系统创建一个新的进程 并在该进程中执行task函数
     # task()    # 同步
     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) # 主进程代码等待3s 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))
    # 主进程代码会在子进程代码运行结束后再去执行
    start_time = time.time()
    p1.start()
    p1.join()  # join使用的位置不同,代码的执行就不同
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    print(time.time() - start_time)   # 结果是6s多,原因是每次执行昂完当前任务才会执行下一个

   # 所有进程同时进行
    start_time = time.time()
    p1.start()
    p2.start()
    p3.start()
    p1.join()  # join使用的位置不同,代码的执行就不同
    p2.join()
    p3.join()
    print(time.time() - start_time)  # 结果是3s多,开启所有进程运行,最后完成的进程就是全部花费的时间
复制代码

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.empty())# 判断队列是否为空
print(q.get())
print(q.get())
print(q.get_nowait())  # 自定义异常,使其变为阻塞
"""full()和empty()在多进程中都不能使用"""

from multiprocessing import Process,Queue

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__':
     p = Process(target=task, args=('1',))
     p.daemon = True  
         # 此代码将子进程设置为守护进程:主进程代码结束,子进程立刻结束。且必须在start之前执行
     p.start()
     print('预言家被刀出局!!!')
复制代码

孤儿进程与僵尸进程

僵尸进程: 进程已经运行结束 但是相关的资源并没有完全清空
      需要父进程参与回收
孤儿进程: 父进程意外死亡 子进程正常运行 该子进程就称之为孤儿进程
      孤儿进程也不是没有人管 操作系统会自动分配资源接收

多进程数据错乱问题

复制代码
# 1. 多进程操作数据很可能会造成数据错乱>>>:互斥锁
# 2. 互斥锁:将并发变成串行,牺牲了效率但是保障了数据的安全


"""模拟12306"""
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 @   橘子菌菌n  阅读(170)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示