通过刚刚的学习,我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题:当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

一、多进程抢占输出资源

import os
import time
import random
from multiprocessing import Process def work(n):
print('%s: %s is running' %(n,os.getpid()))
time.sleep(random.random())
print('%s:%s is done' %(n,os.getpid())) if __name__ == '__main__':
for i in range(3):
p=Process(target=work,args=(i,))
p.start()

二、使用锁维护执行顺序

# 由并发变成了串行,牺牲了运行效率,但避免了竞争
import os
import time
import random
from multiprocessing import Process,Lock def work(lock,n):
lock.acquire()
print('%s: %s is running' % (n, os.getpid()))
time.sleep(random.random())
print('%s: %s is done' % (n, os.getpid()))
lock.release()
if __name__ == '__main__':
lock=Lock()
for i in range(3):
p=Process(target=work,args=(lock,i))
p.start()

上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。

接下来,我们以模拟抢票为例,来看看数据安全的重要性。

三、多进程同时抢购余票

# 文件db的内容为:{"count":1}
# 注意一定要用双引号,不然json无法识别
# 并发运行,效率高,但竞争写同一文件,数据写入错乱
from multiprocessing import Process,Lock
import time,json,random
def search():
dic=json.load(open('db'))
print('剩余票数%s' %dic['count']) def get():
dic=json.load(open('db'))
time.sleep(0.1) # 模拟读数据的网络延迟
if dic['count'] >0:
dic['count']-=1
time.sleep(0.2) # 模拟写数据的网络延迟
json.dump(dic,open('db','w'))
print('购票成功') def task():
search()
get() if __name__ == '__main__':
for i in range(100): # 模拟并发100个客户端抢票
p=Process(target=task)
p.start()

四、使用锁来保证数据安全

# 文件db的内容为:{"count":5}
# 注意一定要用双引号,不然json无法识别
# 并发运行,效率高,但竞争写同一文件,数据写入错乱
from multiprocessing import Process,Lock
import time,json,random
def search():
dic=json.load(open('db'))
print('剩余票数%s' %dic['count']) def get():
dic=json.load(open('db'))
time.sleep(random.random()) # 模拟读数据的网络延迟
if dic['count'] >0:
dic['count']-=1
time.sleep(random.random()) # 模拟写数据的网络延迟
json.dump(dic,open('db','w'))
print('购票成功')
else:
print('购票失败') def task(lock):
search()
lock.acquire()
get()
lock.release() if __name__ == '__main__':
lock = Lock()
for i in range(100): # 模拟并发100个客户端抢票
p=Process(target=task,args=(lock,))
p.start()

加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。

虽然可以用文件共享数据实现进程间通信,但问题是:

  1. 效率低(共享数据基于文件,而文件是硬盘上的数据)
  2. 需要自己加锁处理

因此我们最好找寻一种解决方案能够兼顾:

  1. 效率高(多个进程共享一块内存的数据)
  2. 帮我们处理好锁问题。这就是mutiprocessing模块为我们提供的基于消息的IPC通信机制:队列和管道。

队列和管道都是将数据存放于内存中,队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来,我们应该尽量避免使用共享数据,尽可能使用消息传递和队列,避免处理复杂的同步和锁问题,而且在进程数目增多时,往往可以获得更好的可获展性。

Python程序中的进程操作-进程同步(multiprocess.Lock)的更多相关文章

  1. Python程序中的进程操作-进程间通信(multiprocess.Queue)

    目录 一.进程间通信 二.队列 2.1 概念介绍--multiprocess.Queue 2.1.1 方法介绍 2.1.2 其他方法(了解) 三.代码实例--multiprocess.Queue 3. ...

  2. 在Python程序中的进程操作,multiprocess.Process模块

    在python程序中的进程操作 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起 ...

  3. python 全栈开发,Day38(在python程序中的进程操作,multiprocess.Process模块)

    昨日内容回顾 操作系统纸带打孔计算机批处理 —— 磁带 联机 脱机多道操作系统 —— 极大的提高了CPU的利用率 在计算机中 可以有超过一个进程 进程遇到IO的时候 切换给另外的进程使用CPU 数据隔 ...

  4. Python程序中的进程操作--—--开启多进程

    Python程序中的进程操作-----开启多进程 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创 ...

  5. 29、Python程序中的进程操作(multiprocess.process)

    一.multiprocess模块 multiprocess不是一个模块而是python中一个操作.管理进程的包. 子模块分为四个部分: 创建进程部分 进程同步部分 进程池部分 进程之间数据共享 二.m ...

  6. 在python程序中的进程操作

    multiprocess模块 multiprocess不是一个模块而是python中一个操作.管理进程的包. 之所以叫multi是取自multiple的多功能的意思,在这个包中几乎包含了和进程有关的所 ...

  7. Python程序中的进程操作-开启多进程(multiprocess.process)

    目录 一.multiprocess模块 二.multiprocess.process模块 三.process模块介绍 3.1 方法介绍 3.2 属性介绍 3.3 在windows中使用process模 ...

  8. Python程序中的进程操作-进程池(multiprocess.Pool)

    目录 一.进程池 二.概念介绍--multiprocess.Pool 三.参数用法 四.主要方法 五.其他方法(了解) 六.代码实例--multiprocess.Pool 6.1 同步 6.2 异步 ...

  9. Python程序中的进程操作

    之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起来的python程序也是一个进程 ...

随机推荐

  1. 在Vue中添加css扩展语言sass

    npm install vue-loader --save-dev npm install node-sass --save-dev npm install sass-loader --save-de ...

  2. Server基本语句的用法

    1.创建数据库 create database databaseName use databaseName go   /*  转到指定数据库 */ 2.创建表 create table tableNa ...

  3. dpwwn:2 Vulnhub Walkthrough

    此镜像配置了静态IP地址:10.10.10.10,需要调整下网络 主机层扫描: ╰─ nmap -p1-65535 -sV -A 10.10.10.10 80/tcp    open  http    ...

  4. [转]UIpath advanced certification dumps

    本文转自:https://dotnetbasic.com/2019/06/uipath-advanced-certification-dumps.html UiPath advanced certif ...

  5. iOS开发WKWebView 返回H5上级页面

    #pragma mark ---- 点击事件 -(void)leftTapClick:(UITapGestureRecognizer *)sender{ //判断是否能返回到H5上级页面 if (se ...

  6. C#&.Net干货分享- 构造BaiduLanguageHelper对接百度的语言翻译

    全部是封装的API源码... namespace Frame.Api{    /// <summary>    /// 百度多语言支持器    /// </summary>   ...

  7. 并发编程~~~协程~~~greenlet模块, gevent模块

    一 协程 1. 协程: 单线程下的并发,又称微线程,纤程.协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 并发真正的核心: 切换并且保持状态. 开启协程并发的执行,自己的程序把控着C ...

  8. 安装oracle11g服务端

    1.将oracle11g压缩包 解压到D盘根目录下 2.打开解压出来的文件夹,以管理员身份运行setup 3.警告弹框点击“是(Y)” 4.在此步骤中,可以提供您的电子邮件,以获取有关Oracle安全 ...

  9. 剑指Offer-37.二叉树的深度(C++/Java)

    题目: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 分析: 递归求解左右子树的最大值即可,每遍历到一个结点,深度加1,最后 ...

  10. 如何用node.js中的ejs写入页面_以6.19京东秒杀的商品为例

    用erpress搭建好基本框架后,在自己新建的express文件夹下将会生成;bin,public,routes,views,app.js,package.json,node_modules目录哟!, ...