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 translator使用实例
Sep 06 Python
Python入门之modf()方法的使用
May 15 Python
Python序列循环移位的3种方法推荐
Apr 09 Python
Python实现的多项式拟合功能示例【基于matplotlib】
May 15 Python
python 自动去除空行的实例
Jul 24 Python
解决Tensorboard 不显示计算图graph的问题
Feb 15 Python
Python爬虫requests库多种用法实例
May 28 Python
python在CMD界面读取excel所有数据的示例
Sep 28 Python
python切割图片的示例
Nov 12 Python
Python Selenium操作Cookie的实例方法
Feb 28 Python
Python列表删除重复元素与图像相似度判断及删除实例代码
May 07 Python
如何使用python包中的sched事件调度器
Apr 30 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读取XML值的代码(推荐)
2011/01/01 PHP
php 目录遍历、删除 函数的使用介绍
2013/04/28 PHP
PHP获取网页标题的3种实现方法代码实例
2014/04/11 PHP
Laravel给生产环境添加监听事件(SQL日志监听)
2017/06/19 PHP
laravel如何开启跨域功能示例详解
2017/08/31 PHP
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
使用javascipt---实现二分查找法
2013/04/10 Javascript
JS实现程序暂停与继续功能代码解读
2013/10/10 Javascript
JavaScript实现级联菜单的方法
2015/06/29 Javascript
js实现鼠标点击文本框自动选中内容的方法
2015/08/20 Javascript
再次谈论Javascript中的this
2016/06/23 Javascript
Webpack实现按需打包Lodash的几种方法详解
2017/05/08 Javascript
vue中如何使用ztree
2018/02/06 Javascript
详解ES6 export default 和 import语句中的解构赋值
2019/05/28 Javascript
vue项目打包之开发环境和部署环境的实现
2020/04/23 Javascript
vue实现图片上传功能
2020/05/28 Javascript
微信小程序实现canvas分享朋友圈海报
2020/06/21 Javascript
vuex中store存储store.commit和store.dispatch的用法
2020/07/24 Javascript
uniapp开发小程序实现滑动页面控制元素的显示和隐藏效果
2020/12/10 Javascript
[01:10]DOTA2英雄背景故事第四期之混沌法则混沌骑士
2020/07/16 DOTA
Python基于checksum计算文件是否相同的方法
2015/07/09 Python
Python简易版图书管理系统
2019/08/12 Python
使用Python给头像加上圣诞帽或圣诞老人小图标附源码
2019/12/25 Python
Python脚本实现监听服务器的思路代码详解
2020/05/28 Python
html5 canvas 简单画板实现代码
2012/01/05 HTML / CSS
瑰珀翠美国官网:Crabtree & Evelyn美国
2016/11/29 全球购物
吉列剃须刀美国官网:Gillette美国
2018/07/13 全球购物
Happy Socks英国官网:购买五颜六色的袜子
2020/11/03 全球购物
医务人员竞聘职务自我评价分享
2013/11/08 职场文书
运动会四百米广播稿
2014/01/19 职场文书
数控专业个人求职信范文
2014/02/05 职场文书
国际商务英语专业求职信
2014/07/08 职场文书
2014领导干部学习焦裕禄同志先进事迹思想汇报
2014/09/19 职场文书
python基础入门之字典和集合
2021/06/13 Python
nginx配置虚拟主机的详细步骤
2021/07/21 Servers
详解Nginx 被动检查服务器的存活状态
2021/10/16 Servers