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中__init__和__new__的区别详解
Jul 09 Python
python实现从字典中删除元素的方法
May 04 Python
Python中MySQLdb和torndb模块对MySQL的断连问题处理
Nov 09 Python
Python中字符串的处理技巧分享
Sep 17 Python
Python实现的快速排序算法详解
Aug 01 Python
python中实现精确的浮点数运算详解
Nov 02 Python
Python连接Redis的基本配置方法
Sep 13 Python
Python实现随机创建电话号码的方法示例
Dec 07 Python
python绘制多个子图的实例
Jul 07 Python
用Python将Excel数据导入到SQL Server的例子
Aug 24 Python
关于windows下Tensorflow和pytorch安装教程
Feb 04 Python
python中doctest库实例用法
Dec 31 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
Yii入门教程之Yii安装及hello world
2014/11/25 PHP
PHP使用PHPExcel删除Excel单元格指定列的方法
2016/07/06 PHP
通过代码实例解析PHP session工作原理
2020/12/11 PHP
DHTML Slide Show script图片轮换
2008/03/03 Javascript
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
Iframe 自动适应页面的高度示例代码
2014/02/26 Javascript
jquery中ajax函数执行顺序问题之如何设置同步
2014/02/28 Javascript
弹出遮罩层后禁止滚动效果【实现代码】
2016/04/29 Javascript
用NodeJS实现批量查询地理位置的经纬度接口
2016/08/16 NodeJs
JS实现获取来自百度,Google,soso,sogou关键词的方法
2016/12/21 Javascript
js中的面向对象入门
2017/03/06 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
Node 自动化部署的方法
2017/10/17 Javascript
nodejs+mongodb+vue前后台配置ueditor的示例代码
2018/01/02 NodeJs
Echarts动态加载多条折线图的实现代码
2019/05/24 Javascript
JS实现排行榜文字向上滚动轮播效果
2019/11/26 Javascript
javascript浅层克隆、深度克隆对比及实例解析
2020/02/09 Javascript
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
2017/09/08 Python
Python算法之图的遍历
2017/11/16 Python
python机器学习实战之树回归详解
2017/12/20 Python
对Python3+gdal 读取tiff格式数据的实例讲解
2018/12/04 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
在python tkinter界面中添加按钮的实例
2020/03/04 Python
HTML5仿微信聊天界面、微信朋友圈实例代码
2018/01/29 HTML / CSS
澳大利亚宠物商店:Petbarn
2017/11/18 全球购物
柏林通行证:Berlin Pass
2018/04/11 全球购物
美国在线眼镜店:GlassesShop
2018/11/15 全球购物
Myprotein丹麦官网:欧洲第一运动营养品牌
2019/04/15 全球购物
工程测量与监理专业应届生求职信
2013/11/27 职场文书
妇女工作先进事迹
2014/08/17 职场文书
房产公证书格式
2015/01/26 职场文书
长江三峡导游词
2015/01/31 职场文书
三潭印月的导游词
2015/02/12 职场文书
装饰施工员岗位职责
2015/04/11 职场文书
高中议论文(范文2篇)
2019/08/19 职场文书