Python-进程(2)
进程互斥锁
通过之前的学习,我们千方百计的实现了程序的异步,让多个任务可以同时在几个进程中并发处理
他们之间的运行没有顺序,一旦开启也不受我们的控制,随之而来的带来了新的问题:
当多个进程使用同一份数据资源的时候,就会引起数据安全或数据混乱问题
# coding=utf-8
import os
import time
import random
from multiprocessing import Process,Lock
def work(n):
print('%s: %s is running' %(n,os.getpid()))
time.sleep(random.random())
print('%s:%s is done' %(n,os.getpid()))
def run(n,lock):
lock.acquire()
work(n)
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(3):
p=Process(target=run,args=(i,lock))
p.start()
2: 6616 is running
2:6616 is done
0: 7052 is running
0:7052 is done
1: 10752 is running
1:10752 is done
上面情况使用加锁实现顺序执行,程序由并发执行变成了串行执行。
以模拟抢票软件为例,验证数据的重要性
data 文件内容:{"count": 0}
# coding=utf-8
from multiprocessing import Process,Lock
import json
import time
# 查看余票
def search(user):
# 打开data文件查看余票
with open("data","r",encoding="utf-8") as f:
dic = json.load(f)
print(f"{user} 查看余票,还剩{dic.get('count')}")
# 买票
def buy(user):
# 先打开文件获取车票数据
with open("data","r",encoding="utf-8") as f:
dic = json.load(f)
# 模拟网络延迟
time.sleep(1)
# 若有票修改data数据
if dic.get("count") > 0:
dic["count"] -= 1
with open("data","w",encoding="utf-8") as f:
json.dump(dic,f)
print(f"{user} 抢到了车票!")
else:
print(f"{user} 抢票失败")
def run(user,lock):
search(user)
# 锁住
lock.acquire()
buy(user)
# 释放锁
lock.release()
# 给buy函数添加锁,让并发变成了串行
# 牺牲了执行效率,但保证了数据的安全
# 在程序并发执行时,需要修改数据时使用互斥锁
if __name__ == '__main__':
# 创建一把锁
lock = Lock()
# 模拟并发10个客户端抢票
for i in range(10):
p = Process(target=run,args=(f"服务器 {i} ",lock))
p.start()
服务器 2 查看余票,还剩1
服务器 3 查看余票,还剩1
服务器 7 查看余票,还剩1
服务器 6 查看余票,还剩1
服务器 2 抢到了车票!
服务器 0 查看余票,还剩0
服务器 8 查看余票,还剩0
服务器 4 查看余票,还剩0
服务器 1 查看余票,还剩0
服务器 9 查看余票,还剩0
服务器 5 查看余票,还剩0
服务器 3 抢票失败
服务器 7 抢票失败
服务器 6 抢票失败
服务器 0 抢票失败
服务器 8 抢票失败
服务器 4 抢票失败
服务器 1 抢票失败
服务器 9 抢票失败
服务器 5 抢票失败
加锁可以保证多个进程在修改同一块数据的时候,同一时间只能有一个任务可以进行修改,即串行的修改,这样速度是慢了,但是保证了数据的安全。
队列
相当于在内存中产生一个队列空间,可以存放多个数据,遵循先进先出原则
# coding=utf-8
from multiprocessing import Queue
'''
Queue 用法:
'''
# 创建出q对象,Queue类可以传参数(),
# 5表示可以存5个值
# 若不填可以存无限个值
q = Queue(5)
# 添加数据
q.put("1")
q.put("2")
q.put("3")
q.put("4")
q.put("5")
# 查看队列中是否满了 True
print(q.full())
# 继续添加数据,若队列满了就报错 queue.Full
q.put_nowait("6")
# 获取数据,遵循先进先出,,若队列中无数据可取,也会卡主
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# 判断队列是否为空 True
print(q.empty())
# 继续获取数据,若队列中没有数据了就报错 queue.Empty
print(q.get_nowait())
堆栈
堆栈是一个后进先出的数据结构,工作方式就像一对汽车排队进去一个死胡同里面,最先进去的一定是最后出来
IPC(进程间通信)
进程间数据时相互隔离的,若想实现进程间通信,可以利用队列。
# coding=utf-8
from multiprocessing import Process
from multiprocessing import Queue
def test1(q):
data = "数据"
# 添加队列数据
q.put(data)
print("子进程1开始添加数据到队列中")
def test2(q):
# 获取队列数据
data = q.get()
print(f"子进程2从队列中获取数据:{data}")
if __name__ == '__main__':
q = Queue()
p1 = Process(target=test1,args=(q,))
p2 = Process(target=test2,args=(q,))
p1.start()
p2.start()
print("主程序")
生产者与消费者模型
生产者:生产数据的
消费者:使用数据的
生活中:比如卖油条,一边生产油条,一边买油条,供需不平衡
程序中:通过队列,生产者把数据添加队列中,消费者从队列中获取数据
# coding=utf-8
from multiprocessing import Process,Queue
import time
# 生产者
def producer(name,food,q):
for i in range(10):
data = food,i
print(f"用户{name} 制作了{data}")
q.put(data)
time.sleep(0.1)
# 消费者
def consumer(name,q):
while True:
# time.sleep(1)
data = q.get()
if not data:
break
print(f"用户{name} 开始吃{data}")
if __name__ == '__main__':
q = Queue()
# 创造生产者
p1 = Process(target=producer,args=("qinyj","油条",q))
# 创造消费者
c1 = Process(target=consumer,args=("qinyj",q))
p1.start()
# 添加消费者守护进程,表示跟着主程序一起停掉,即生产者不生产了,消费者也不吃了
c1.daemon = True
c1.start()
# 添加join方法,生产者生产完毕之后就停掉,然后消费者也会一直吃
p1.join()
# time.sleep(10) # 添加延迟,等待生产者生产完毕把所有进程死掉
print("主程序")
用户qinyj 制作了('油条', 0)
用户qinyj 开始吃('油条', 0)
用户qinyj 制作了('油条', 1)
用户qinyj 开始吃('油条', 1)
用户qinyj 制作了('油条', 2)
用户qinyj 开始吃('油条', 2)
用户qinyj 制作了('油条', 3)
用户qinyj 开始吃('油条', 3)
用户qinyj 制作了('油条', 4)
用户qinyj 开始吃('油条', 4)
用户qinyj 制作了('油条', 5)
用户qinyj 开始吃('油条', 5)
用户qinyj 制作了('油条', 6)
用户qinyj 开始吃('油条', 6)
用户qinyj 制作了('油条', 7)
用户qinyj 开始吃('油条', 7)
用户qinyj 制作了('油条', 8)
用户qinyj 开始吃('油条', 8)
用户qinyj 制作了('油条', 9)
用户qinyj 开始吃('油条', 9)
主程序
Python-进程(2)的更多相关文章
- python——进程基础
我们现在都知道python的多线程是个坑了,那么多进程在这个时候就变得很必要了.多进程实现了多CPU的利用,效率简直棒棒哒~~~ 拥有一个多进程程序: #!/usr/bin/env python #- ...
- 使用gdb调试Python进程
使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...
- python进程、线程、协程(转载)
python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...
- Python进程、线程、协程详解
进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...
- python进程池剖析(一)
python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序.如果需要 ...
- python——进程、线程、协程
Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...
- python/进程线程的总结
python/进程线程的总结 一.进程和线程的描述: 进程:最小的资源管理单位 线程:最小的执行单位 执行一个进程时就默认执行一个线程(主线程) 进程和线程的工作方式: 串行: 假如共有A.B.C任务 ...
- python 进程介绍 进程简单使用 join 验证空间隔离
一.多道程序设计技术(详情参考:https://www.cnblogs.com/clschao/articles/9613464.html) 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行 ...
- Python 进程之间共享数据
最近遇到多进程共享数据的问题,到网上查了有几篇博客写的蛮好的,记录下来方便以后查看. 一.Python multiprocessing 跨进程对象共享 在mp库当中,跨进程对象共享有三种方式,第一种 ...
- python进程、多进程
进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当 ...
随机推荐
- JVM内核-原理、诊断与优化学习笔记(八):JAVA堆分析
文章目录 内存溢出(OOM)的原因 在JVM中,有哪些内存区间? 堆溢出 永久区 Java栈溢出 直接内存溢出 小问题? MAT使用基础 柱状图显示 支配树 显示线程信息 显示堆总体信息,比如消耗最大 ...
- (转)Python学习笔记(1)__name__变量
Python使用缩进对齐组织代码的执行,所有没有缩进的代码,都会在载入时自动执行.每个文件(模块)都可以任意写一些没有缩进的代码,并在载入时自动执行.为了区分 主执行代码和被调用文件,Python引入 ...
- 增量+全量备份SVN服务器
#!/bin/bash # 获取当前是星期几 DAY=$(date +%w) # 获取当前的日期 DATE=$(date '+%Y-%m-%d-%H-%M') # 获取当前版本库中最新的版本 CURR ...
- JAVA时间工具类用法
1.获得N天前的TIMESTAMP Calendar cl = Calendar.getInstance(); cl.add(Calendar.DAY_OF_YEAR, -7); Date date ...
- pointer && reference
关注点在于区别两者之间的不同. 我们可以从两者使用的场景进行区分: 1, 是否需要存在null的情况: YES-pointer NO-reference 如果确定不会存在null的情况,那么使用ref ...
- YARN设计思路
- lds 文件说明
主要符号说明 OUTPUT_FORMAT(bfdname) 指定输出可执行文件格式. OUTPUT_ARCH(bfdname) 指定输出可执行文件所运行 CPU 平台 ENTRY(symbol) 指定 ...
- CSIC_716_20191109【函数的语法,以及函数的分类,可变长参数*args】
函数 定义.作用.及使用方式 函数是一种工具,可以被重复调用. 使用函数可精简重复代码,减少冗余,增加代码的可读性. 函数要先构造函数,然后调用函数. 构造及调用函数的语法结构 关键字def 函数名 ...
- 使用Element的upload上传组件,不使用action属性上传
1.需要实现的效果如下图,在点击提交的时候再提交file数据,和其他数据统一上传,我把file转换成了base64的格式,可以再上传之前显示缩略图 2.代码分析 action属性值为"#&q ...
- 帆软报表PC端实施报表心得体会
1.报表制作完成后,预览时自动显示查询内容,在控件处设置: 2.求一列数据的最小值(除去0),并对最小值字体加粗标绿,需要对对应单元格设置条件属性,并插入公式:C6 = min(greparray(C ...