通过刚刚的学习,我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用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. html中的a标签详解

    事故起源于一个魔鬼测试人员,某天做网站UI优化的时候,突然甩了一个问题给我 第二列的数据是可以跳转至其他页面的,但是,魔鬼测试的电脑上,一直都有一条数据是与其他的样式不同,于是便甩了这个问题给我,我一 ...

  2. Android8.1 SystemUI源码分析之 电池时钟刷新

    SystemUI源码分析相关文章 Android8.1 SystemUI源码分析之 Notification流程 分析之前再贴一下 StatusBar 相关类图 电池图标刷新 从上篇的分析得到电池图标 ...

  3. react-router刷新页面Cannot GET 问题

    最近在做项目的时候遇到了如下错误 并在控制台看到了如下的报错 我先是按照控制台的错误搜索,得出的结果都是对meta头部进行设置,允许资源请求,但是问题依然没有解决,偶然间改变了想法,会不会是路由的问题 ...

  4. 49-在 overlay 中运行容器

    上一节我们创建了 overlay 网络 ov_net1,今天将运行一个 busybox 容器并连接到 ov_net1: 查看容器的网络配置: bbox1 有两个网络接口 eth0 和 eth1.eth ...

  5. Troubleshooting: High Version Count Issues

    --查询版本高的原因 select * from v$sql_shared_cursor where sql_id=''; Configuring Download the script in the ...

  6. linux下安装make工具

    安装make工具 make工具依赖gcc ,automake,autoconf,libtool,make 这些安装包 可以一起安装 center os系统 运行如下命令yum install gcc ...

  7. SpringCloudGateWay修改请求路径,从注册中心获得服务

    SpringCloudGateWay修改请求路径,从注册中心获得服务 @Resource    private DiscoveryClient disClient;    @Resource    p ...

  8. spring boot 加入mail邮件支持

    一.添加依赖 <!-- 邮件整合 --> <dependency> <groupId>org.springframework.boot</groupId> ...

  9. 关于Mysql修改帐号密码的多种方法

    方法一: 登录Mysql进行修改(mysql的小黑框) 命令: set password for 用户名(一般为root) @localhost=password('新密码'); 方法二: 登录MyS ...

  10. nginx 反向代理之 proxy_pass

    格式很简单: proxy_pass URL; 其中URL包含:传输协议(http://, https://等).主机名(域名或者IP:PORT).uri. 示例如下: proxy_pass http: ...