python并发编程多进程 模拟抢票实现过程


Posted in Python onAugust 20, 2019

 抢票是并发执行

多个进程可以访问同一个文件

多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务

db.txt

{"count": 1}

并发运行,效率高,但竞争写同一文件,数据写入错乱,只有一张票,都卖成功给了10个人

#文件db.txt的内容为:{"count":1}
#注意一定要用双引号,不然json无法识别
from multiprocessing import Process
import time
import json
class Foo(object):
  def search(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)
      time.sleep(1) # 模拟读数据的网络延迟
      print("<%s>用户 查看剩余票数为 [%s]" % (name, dic["count"]))
  def get(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)
      if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(1) # 模拟写数据的网络延迟
        with open("db.txt", "w") as f_write:
          json.dump(dic, f_write)
          print("<%s> 购票成功" % name)
          print("剩余票数为 [%s]" % dic["count"])
      else:
        print("没票了,抢光了")
  def task(self, name):
    self.search(name)
    self.get(name)
if __name__ == "__main__":
  obj = Foo()
  for i in range(1,11):  # 模拟并发10个客户端抢票
    p = Process(target=obj.task, args=("路人%s" % i,))
    p.start()

总结:程序出现数据写入错乱

大家都查到票为1,都购票成功

<路人1>用户 查看剩余票数为 [1]
<路人2>用户 查看剩余票数为 [1]
<路人3>用户 查看剩余票数为 [1]
<路人4>用户 查看剩余票数为 [1]
<路人5>用户 查看剩余票数为 [1]
<路人6>用户 查看剩余票数为 [1]
<路人7>用户 查看剩余票数为 [1]
<路人8>用户 查看剩余票数为 [1]
<路人9>用户 查看剩余票数为 [1]
<路人10>用户 查看剩余票数为 [1]
<路人1> 购票成功
剩余票数为 [0]
<路人2> 购票成功
剩余票数为 [0]
<路人3> 购票成功
剩余票数为 [0]
<路人4> 购票成功
剩余票数为 [0]
<路人5> 购票成功
剩余票数为 [0]
<路人6> 购票成功
剩余票数为 [0]
<路人7> 购票成功
剩余票数为 [0]
<路人8> 购票成功
剩余票数为 [0]
<路人9> 购票成功
剩余票数为 [0]
<路人10> 购票成功
剩余票数为 [0]

总结程序出现数据写入错乱

加锁处理:购票行为由并发变成了串行,牺牲了运行效率,但保证了数据安全

购票功能不应该并发执行,查票应该是并发执行的

查票准不准确不重要,有可能这张票就被别人买走

一个人写完以后,让另外一个人基于上一个人写的结果,再做购票操作

#把文件db.txt的内容重置为:{"count":1}
from multiprocessing import Process
from multiprocessing import Lock
import time
import json
class Foo(object):
  def search(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)
      time.sleep(1) # 模拟读数据的网络延迟
      print("<%s>用户 查看剩余票数为 [%s]" % (name, dic["count"]))
  def get(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)
      if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(1) # 模拟写数据的网络延迟
        with open("db.txt", "w") as f_write:
          json.dump(dic, f_write)
          print("<%s> 购票成功" % name)
          print("剩余票数为 [%s]" % dic["count"])
      else:
        print("没票了,抢光了")
  def task(self, name, mutex):
    self.search(name)
    mutex.acquire()
    self.get(name)
    mutex.release()
if __name__ == "__main__":
  mutex = Lock()
  obj = Foo()
  for i in range(1,11): # 模拟并发10个客户端抢票
    p = Process(target=obj.task, args=("路人%s" % i, mutex))
    p.start()

执行结果

<路人2>用户 查看剩余票数为 [1]
<路人3>用户 查看剩余票数为 [1]
<路人1>用户 查看剩余票数为 [1]
<路人4>用户 查看剩余票数为 [1]
<路人5>用户 查看剩余票数为 [1]
<路人7>用户 查看剩余票数为 [1]
<路人6>用户 查看剩余票数为 [1]
<路人8>用户 查看剩余票数为 [1]
<路人9>用户 查看剩余票数为 [1]
<路人10>用户 查看剩余票数为 [1]
<路人2> 购票成功
剩余票数为 [0]
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了
没票了,抢光了

with lock

相当于lock.acquire(),执行完自代码块自动执行lock.release()

from multiprocessing import Process
from multiprocessing import Lock
import time
import json
class Foo(object):
  def search(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)

      time.sleep(1) # 模拟读数据的网络延迟
      print("<%s>用户 查看剩余票数为 [%s]" % (name, dic["count"]))
  def get(self, name):
    with open("db.txt", "r") as f_read:
      dic = json.load(f_read)
      if dic["count"] > 0:
        dic["count"] -= 1
        time.sleep(1) # 模拟写数据的网络延迟
        with open("db.txt", "w") as f_write:
          json.dump(dic, f_write)
          print("<%s> 购票成功" % name)
          print("剩余票数为 [%s]" % dic["count"])
      else:
        print("没票了,抢光了")
  def task(self, name, mutex):
    self.search(name)
    with mutex: # 相当于lock.acquire(),执行完自代码块自动执行lock.release()
      self.get(name)
if __name__ == "__main__":
  mutex = Lock()
  obj = Foo()
  for i in range(1,11): # 模拟并发10个客户端抢票
    p = Process(target=obj.task, args=("路人%s" % i, mutex))
    p.start()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python发送邮件示例(支持中文邮件标题)
Feb 16 Python
python使用MySQLdb访问mysql数据库的方法
Aug 03 Python
Python中的集合类型知识讲解
Aug 19 Python
python使用正则表达式的search()函数实现指定位置搜索功能
Nov 10 Python
Python使用PIL模块生成随机验证码
Nov 21 Python
Python 用matplotlib画以时间日期为x轴的图像
Aug 06 Python
Python基本语法之运算符功能与用法详解
Oct 22 Python
Cython编译python为so 代码加密示例
Dec 23 Python
python 获取当前目录下的文件目录和文件名实例代码详解
Mar 10 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
Jun 04 Python
python如何实现DES加密
Sep 21 Python
详解如何使用Pytest进行自动化测试
Jan 14 Python
python3的数据类型及数据类型转换实例详解
Aug 20 #Python
Python列表的切片实例讲解
Aug 20 #Python
python并发编程多进程 互斥锁原理解析
Aug 20 #Python
django 配置阿里云OSS存储media文件的例子
Aug 20 #Python
python数据类型之间怎么转换技巧分享
Aug 20 #Python
python并发编程多进程之守护进程原理解析
Aug 20 #Python
python控制台实现tab补全和清屏的例子
Aug 20 #Python
You might like
PHP URL路由类实例
2013/11/12 PHP
PHP函数rtrim()使用中的怪异现象分析
2017/02/24 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
2020/06/02 PHP
用jscript实现列出安装的软件列表
2007/06/18 Javascript
Node.js中使用计时器定时执行函数详解
2014/08/15 Javascript
javascript使用数组的push方法完成快速排序
2014/09/15 Javascript
JavaScript中使用Object.create()创建对象介绍
2014/12/30 Javascript
jQuery获取页面及个元素高度、宽度的总结——超实用
2015/07/28 Javascript
JS实现状态栏跑马灯文字效果代码
2015/10/24 Javascript
JS中JSON对象和String之间的互转及处理技巧
2016/04/06 Javascript
JS实现的驼峰式和连字符式转换功能分析
2016/12/21 Javascript
vue.js 微信支付前端代码分享
2018/02/10 Javascript
JavaScript 跨域之POST实现方法
2018/05/07 Javascript
Vue-不允许嵌套式的渲染方法
2018/09/13 Javascript
命令行批量截图Node脚本示例代码
2019/01/25 Javascript
使用Bootstrap做一个朝代历史表
2019/12/10 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
[02:28]DOTA2英雄基础教程 灰烬之灵
2013/12/19 DOTA
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
深入解析Python中的WSGI接口
2015/05/11 Python
Python3 处理JSON的实例详解
2017/10/29 Python
机器学习python实战之手写数字识别
2017/11/01 Python
Python函数定义及传参方式详解(4种)
2019/03/18 Python
Python中函数的基本定义与调用及内置函数详解
2019/05/13 Python
在PyTorch中使用标签平滑正则化的问题
2020/04/03 Python
解决python脚本中error: unrecognized arguments: True错误
2020/04/20 Python
Python爬虫入门有哪些基础知识点
2020/06/02 Python
Python使用lambda抛出异常实现方法解析
2020/08/20 Python
Numpy中np.random.rand()和np.random.randn() 用法和区别详解
2020/10/23 Python
类、抽象类、接口的差异
2016/06/13 面试题
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
生产部管理制度
2014/01/31 职场文书
分家协议书
2014/04/21 职场文书
考研英语复习计划
2015/01/19 职场文书
高三毕业感言
2015/07/30 职场文书
20180830晚上第一届KSL半决赛 雨神vs解冻(二龙 三炮解说)
2022/04/01 星际争霸