Python队列、进程间通信、线程案例


Posted in Python onOctober 25, 2019

进程互斥锁

多进程同时抢购余票

# 并发运行,效率高,但竞争写同一文件,数据写入错乱
# data.json文件内容为 {"ticket_num": 1}
import json
import time
from multiprocessing import Process
def search(user):
  with open('data.json', 'r', encoding='utf-8') as f:
    dic = json.load(f)
  print(f'用户{user}查看余票,还剩{dic.get("ticket_num")}...')
def buy(user):
  with open('data.json', 'r', encoding='utf-8') as f:
    dic = json.load(f)

  time.sleep(0.1)
  if dic['ticket_num'] > 0:
    dic['ticket_num'] -= 1
    with open('data.json', 'w', encoding='utf-8') as f:
      json.dump(dic, f)
    print(f'用户{user}抢票成功!')

  else:
    print(f'用户{user}抢票失败')
def run(user):
  search(user)
  buy(user)
if __name__ == '__main__':
  for i in range(10): # 模拟10个用户抢票
    p = Process(target=run, args=(f'用户{i}', ))
    p.start()

使用锁来保证数据安全

# data.json文件内容为 {"ticket_num": 1}
import json
import time
from multiprocessing import Process, Lock
def search(user):
  with open('data.json', 'r', encoding='utf-8') as f:
    dic = json.load(f)
  print(f'用户{user}查看余票,还剩{dic.get("ticket_num")}...')
def buy(user):
  with open('data.json', 'r', encoding='utf-8') as f:
    dic = json.load(f)

  time.sleep(0.2)
  if dic['ticket_num'] > 0:
    dic['ticket_num'] -= 1
    with open('data.json', 'w', encoding='utf-8') as f:
      json.dump(dic, f)
    print(f'用户{user}抢票成功!')

  else:
    print(f'用户{user}抢票失败')
def run(user, mutex):
  search(user)
  mutex.acquire() # 加锁
  buy(user)
  mutex.release() # 释放锁
if __name__ == '__main__':
  # 调用Lock()类得到一个锁对象
  mutex = Lock()

  for i in range(10): # 模拟10个用户抢票
    p = Process(target=run, args=(f'用户{i}', mutex))
    p.start()

进程互斥锁:

让并发变成串行,牺牲了执行效率,保证了数据安全

在程序并发时,需要修改数据使用

队列

队列遵循的是先进先出

队列:相当于内存中一个队列空间,可以存放多个数据,但数据的顺序是由先进去的排在前面。

q.put() 添加数据

q.get() 取数据,遵循队列先进先出

q.get_nowait() 获取队列数据, 队列中没有就会报错

q.put_nowait 添加数据,若队列满了也会报错

q.full() 查看队列是否满了

q.empty() 查看队列是否为空

from multiprocessing import Queue

# 调用队列类,实例化队列对象
q = Queue(5)  # 队列中存放5个数据

# put添加数据,若队列里的数据满了就会卡住
q.put(1)
print('进入数据1')
q.put(2)
print('进入数据2')
q.put(3)
print('进入数据3')
q.put(4)
print('进入数据4')
q.put(5)
print('进入数据5')

# 查看队列是否满了
print(q.full())

# 添加数据, 若队列满了也会报错
q.put_nowait(6)

# q.get() 获取的数据遵循先进先出
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# print(q.get())
print(q.get_nowait())  # 获取队列数据, 队列中没有就会报错

# 判断队列是否为空
print(q.empty())
q.put(6)
print('进入数据6')

进程间通信

IPC(Inter-Process Communication)

进程间数据是相互隔离的,若想实现进程间通信,可以利用队列

from multiprocessing import Process, Queue
def task1(q):
  data = 'hello 你好'
  q.put(data)
  print('进程1添加数据到队列')
def task2(q):
  print(q.get())
  print('进程2从队列中获取数据')
if __name__ == '__main__':
  q = Queue()

  p1 = Process(target=task1, args=(q, ))
  p2 = Process(target=task2, args=(q, ))
  p1.start()
  p2.start()
  print('主进程')

生产者与消费者

在程序中,通过队列生产者把数据添加到队列中,消费者从队列中获取数据

from multiprocessing import Process, Queue
import time


# 生产者
def producer(name, food, q):
  for i in range(10):
    data = food, i
    msg = f'用户{name}开始制作{data}'
    print(msg)
    q.put(data)
    time.sleep(0.1)
# 消费者
def consumer(name, q):
  while True:
    data = q.get()
    if not data:
      break

    print(f'用户{name}开始吃{data}')
if __name__ == '__main__':
  q = Queue()
  p1 = Process(target=producer, args=('neo', '煎饼', q))
  p2 = Process(target=producer, args=('wick', '肉包', q))

  c1 = Process(target=consumer, args=('cwz', q))
  c2 = Process(target=consumer, args=('woods', q))

  p1.start()
  p2.start()
  
  c1.daemon = True
  c2.daemon = True
  c1.start()
  c2.start()
  print('主')

线程

线程的概念

进程与线程都是虚拟单位

进程:资源单位

线程:执行单位

开启一个进程,一定会有一个线程,线程才是真正执行者

开启进程:

  • 开辟一个名称空间,每开启一个进程都会占用一份内存资源
  • 会自带一个线程

开启线程:

  • 一个进程可以开启多个线程
  • 线程的开销远小于进程

注意:线程不能实现并行,线程只能实现并发,进程可以实现并行

线程的两种创建方式

from threading import Thread
import time
# 创建线程方式1
def task():
  print('线程开启')
  time.sleep(1)
  print('线程结束')

if __name__ == '__main__':
  t = Thread(target=task)
  t.start()
# 创建线程方式2
class MyThread(Thread):
  def run(self):
    print('线程开启...')
    time.sleep(1)
    print('线程结束...')
if __name__ == '__main__':
  t = MyThread()
  t.start()

线程对象的方法

from threading import Thread
from threading import current_thread
import time

def task():
  print(f'线程开启{current_thread().name}')
  time.sleep(1)
  print(f'线程结束{current_thread().name}')
if __name__ == '__main__':
  t = Thread(target=task)
  print(t.isAlive())
  # t.daemon = True
  t.start()
  print(t.isAlive())

线程互斥锁

线程之间数据是共享的

from threading import Thread
from threading import Lock
import time

mutex = Lock()
n = 100

def task(i):
  print(f'线程{i}启动')
  global n
  mutex.acquire()
  temp = n
  time.sleep(0.1)
  n = temp - 1
  print(n)
  mutex.release()
  
if __name__ == '__main__':
  t_l = []
  for i in range(100):
    t = Thread(target=task, args=(i, ))
    t_l.append(t)
    t.start()

  for t in t_l:
    t.join()

  print(n)

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

Python 相关文章推荐
Python重新引入被覆盖的自带function
Jul 16 Python
详解Python3.1版本带来的核心变化
Apr 07 Python
Python中处理字符串之endswith()方法的使用简介
May 18 Python
python3实现ftp服务功能(服务端 For Linux)
Mar 24 Python
python实现感知器
Dec 19 Python
python机器学习实战之树回归详解
Dec 20 Python
Python 删除连续出现的指定字符的实例
Jun 29 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
Jul 15 Python
Python 解析pymysql模块操作数据库的方法
Feb 18 Python
Python写捕鱼达人的游戏实现
Mar 31 Python
Python爬虫基础之简单说一下scrapy的框架结构
Jun 26 Python
python标准库ElementTree处理xml
May 20 Python
python银行系统实现源码
Oct 25 #Python
python Event事件、进程池与线程池、协程解析
Oct 25 #Python
python实现简单银行管理系统
Oct 25 #Python
Python银行系统实战源码
Oct 25 #Python
python实现银行管理系统
Oct 25 #Python
Django视图扩展类知识点详解
Oct 25 #Python
Python装饰器使用你可能不知道的几种姿势
Oct 25 #Python
You might like
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同之处小结
2012/03/07 PHP
解析如何屏蔽php中的phpinfo()函数
2013/06/06 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
PHP实现发送微博消息功能完整示例
2019/12/04 PHP
Jquery升级新版本后选择器的语法问题
2010/06/02 Javascript
一个不错的js html页面倒计时可精确到秒
2014/10/22 Javascript
JavaScript中的object转换函数toString()与valueOf()介绍
2014/12/31 Javascript
IE中document.createElement的iframe无法设置属性name的解决方法
2015/09/14 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
javascript实现文字无缝滚动
2016/12/27 Javascript
js实现省份下拉菜单效果
2017/02/15 Javascript
简单实现js拖拽效果
2017/07/25 Javascript
解决vue打包项目后刷新404的问题
2018/03/06 Javascript
vue.js实现格式化时间并每秒更新显示功能示例
2018/07/07 Javascript
Vue实现的父组件向子组件传值功能示例
2019/01/19 Javascript
JS手写一个自定义Promise操作示例
2020/03/16 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
Python实现partial改变方法默认参数
2014/08/18 Python
Python中使用partial改变方法默认参数实例
2015/04/28 Python
详解Python中的type()方法的使用
2015/05/21 Python
Python使用defaultdict读取文件各列的方法
2017/05/11 Python
将python包发布到PyPI和制作whl文件方式
2019/12/25 Python
Python3.7在anaconda里面使用IDLE编译器的步骤详解
2020/04/29 Python
Python大批量搜索引擎图像爬虫工具详解
2020/11/16 Python
挪威太阳镜和眼镜网上商城:SmartBuyGlasses挪威
2016/08/20 全球购物
美国Lolё官网:购买大胆而美丽的女性运动服装
2017/05/22 全球购物
欧洲、亚洲、非洲和拉丁美洲的度假套餐:Great Value Vacations
2019/03/30 全球购物
高中自我鉴定范文
2013/11/03 职场文书
农业资源与环境专业自荐信范文
2013/12/30 职场文书
幼儿生日活动方案
2014/08/27 职场文书
三好学生事迹材料
2014/12/24 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
2015年城管个人工作总结
2015/05/15 职场文书
《给予树》教学反思
2016/03/03 职场文书
oracle覆盖导入dmp文件的2种方法
2021/05/21 Oracle
开发者首先否认《遗弃》被取消的传言
2022/04/11 其他游戏