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 pass 语句使用示例
Mar 11 Python
用Python写冒泡排序代码
Apr 12 Python
对pandas里的loc并列条件索引的实例讲解
Nov 15 Python
详解安装mitmproxy以及遇到的坑和简单用法
Jan 21 Python
python实现控制COM口的示例
Jul 03 Python
使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例
Mar 16 Python
python实现简单坦克大战
Mar 27 Python
Python如何在windows环境安装pip及rarfile
Jun 15 Python
容易被忽略的Python内置类型
Sep 03 Python
python 制作简单的音乐播放器
Nov 25 Python
python使用tkinter实现透明窗体上绘制随机出现的小球(实例代码)
May 17 Python
Pycharm连接远程服务器并远程调试的全过程
Jun 24 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
ThinkPHP的Widget扩展实例
2014/06/19 PHP
CodeIgniter多语言实现方法详解
2016/01/20 PHP
php5.3后静态绑定用法详解
2016/11/11 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
JavaScript中的anchor()方法使用详解
2015/06/08 Javascript
jQuery常用且重要方法汇总
2015/07/13 Javascript
jQuery代码性能优化的10种方法
2016/06/21 Javascript
javascript动画之模拟拖拽效果篇
2016/09/26 Javascript
浅谈vue中数据双向绑定的实现原理
2017/09/14 Javascript
基于Vue2的独立构建与运行时构建的差别(详解)
2017/12/06 Javascript
浅谈Redux中间件的实践
2018/07/27 Javascript
javascript闭包的使用之按钮切换功能
2018/08/30 Javascript
关于node-bindings无法在Electron中使用的解决办法
2018/12/18 Javascript
js实现图片局部放大效果详解
2019/03/18 Javascript
利用原生JS实现data方法示例代码
2019/05/28 Javascript
浅谈vue限制文本框输入数字的正确姿势
2019/09/02 Javascript
Vue项目中使用better-scroll实现菜单映射功能方法
2019/09/11 Javascript
Vue 微信端扫描二维码苹果端却只能保存图片问题(解决方法)
2020/01/19 Javascript
vue实现简易的双向数据绑定
2020/12/29 Vue.js
[49:08]FNATIC vs Infamous 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
Python 变量类型及命名规则介绍
2013/06/08 Python
基于tensorflow加载部分层的方法
2018/07/26 Python
python 图像平移和旋转的实例
2019/01/10 Python
解决python字典对值(值为列表)赋值出现重复的问题
2019/01/20 Python
Python Web框架之Django框架文件上传功能详解
2019/08/16 Python
基于Python脚本实现邮件报警功能
2020/05/20 Python
Python3爬虫关于识别点触点选验证码的实例讲解
2020/07/30 Python
python如何爬取动态网站
2020/09/09 Python
python使用re模块爬取豆瓣Top250电影
2020/10/20 Python
Halston Heritage官网:简洁的日装,稍显奢华的晚装
2018/11/20 全球购物
车辆工程专业求职信
2014/04/28 职场文书
债务追讨授权委托书范本
2014/10/16 职场文书
2015人事行政工作总结范文
2015/05/21 职场文书
史上最全的军训拉歌口号
2015/12/25 职场文书
Vue项目中如何封装axios(统一管理http请求)
2021/05/02 Vue.js
MySQL图形化管理工具Navicat安装步骤
2021/12/04 MySQL