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基于回溯法子集树模板解决全排列问题示例
Sep 07 Python
python中for循环输出列表索引与对应的值方法
Nov 07 Python
PyQt 实现使窗口中的元素跟随窗口大小的变化而变化
Jun 18 Python
利用python求积分的实例
Jul 03 Python
使用Pytorch来拟合函数方式
Jan 14 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
Feb 05 Python
详解Python高阶函数
Aug 15 Python
python破解同事的压缩包密码
Oct 14 Python
Python实现异步IO的示例
Nov 05 Python
详解Pycharm第三方库的安装及使用方法
Dec 29 Python
python利用appium实现手机APP自动化的示例
Jan 26 Python
Python简易开发之制作计算器
Apr 28 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
thinkphp 多表 事务详解
2013/06/17 PHP
destoon实现调用热门关键字的方法
2014/07/15 PHP
ThinkPHP中URL路径访问与模块控制器之间的关系
2014/08/23 PHP
php实现的RSS生成类实例
2015/04/23 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
javascript 常用代码技巧大收集
2009/02/25 Javascript
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
javascript中的绑定与解绑函数应用示例
2013/06/24 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
2013/08/05 Javascript
Egret引擎开发指南之视觉编程
2014/09/03 Javascript
详解JavaScript的while循环的使用
2015/06/03 Javascript
JavaScript学习笔记之取数组中最大值和最小值
2016/03/23 Javascript
基于EasyUI的基础之上实现树形功能菜单
2017/06/28 Javascript
Vue 项目部署到服务器的问题解决方法
2017/12/05 Javascript
从Vuex中取出数组赋值给新的数组,新数组push时报错的解决方法
2018/09/18 Javascript
最简单的JS实现json转csv的方法
2019/01/10 Javascript
vue实现简单加法计算器
2020/10/22 Javascript
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
在Python中使用mongoengine操作MongoDB教程
2015/04/24 Python
用tensorflow构建线性回归模型的示例代码
2018/03/05 Python
Python3 安装PyQt5及exe打包图文教程
2019/01/08 Python
TensorFlow 显存使用机制详解
2020/02/03 Python
python中yield的用法详解
2021/01/13 Python
彻底弄明白CSS3的Media Queries(跨平台设计)
2010/07/27 HTML / CSS
EntityManager都有哪些方法
2013/11/01 面试题
物流管理专业大学生自荐信
2013/10/04 职场文书
保险专业大学生职业规划书
2014/03/03 职场文书
竞争上岗演讲稿范文
2014/05/12 职场文书
家庭教育的心得体会
2014/09/01 职场文书
2014保险公司内勤工作总结
2014/12/16 职场文书
优秀班组事迹材料
2014/12/24 职场文书
个人培训总结
2015/03/05 职场文书
一文帮你理解PReact10.5.13源码
2021/04/03 Javascript
Spring Boot 整合 Apache Dubbo的示例代码
2021/07/04 Java/Android
Redis Cluster 集群搭建你会吗
2021/08/04 Redis
Spring boot admin 服务监控利器详解
2022/08/05 Java/Android