Python3 并发编程2
进程互斥锁
基本概念
- 临界资源: 一次仅允许一个进程使用的资源称为临界资源, 进程间采取互斥的方式, 共享临界资源
- 进程互斥: 一个进程正在访问临界资源, 另一个要访问该资源的进程必须等待
- 让并发变成串形, 牺牲了执行效率, 保证了数据的安全
- 在程序并发执行时, 需要修改时使用
互斥锁的使用
# base_data--->{"ticket_num": 1}
# 模拟抢票软件
import json
import time
from multiprocessing import Process
# 查看余票
def search(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
ticket_num = dic.get('ticket_num')
print(f'用户{user}正在查看余票, 当前余票{ticket_num}张...')
# 购买车票
def buy(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
# 阻塞
time.sleep(1)
if dic.get('ticket_num') > 0:
dic['ticket_num'] -= 1
with open('base_data', 'w', encoding='utf-8') as f1:
json.dump(dic, f1)
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()
'''
用户8正在查看余票, 当前余票1张...
用户6正在查看余票, 当前余票1张...
用户3正在查看余票, 当前余票1张...
用户0正在查看余票, 当前余票1张...
用户4正在查看余票, 当前余票1张...
用户2正在查看余票, 当前余票1张...
用户1正在查看余票, 当前余票1张...
用户7正在查看余票, 当前余票1张...
用户5正在查看余票, 当前余票1张...
用户9正在查看余票, 当前余票1张...
用户[8]抢票成功!
用户[6]抢票成功!
用户[3]抢票成功!
用户[4]抢票成功!
用户[1]抢票成功!
用户[5]抢票成功!
用户[2]抢票成功!
用户[0]抢票成功!
用户[7]抢票成功!
用户[9]抢票成功!
'''
使用进程锁将并发变成串行
# 模拟抢票软件
import json
import time
from multiprocessing import Process
from multiprocessing import Lock
# 查看余票
def search(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
ticket_num = dic.get('ticket_num')
print(f'用户[{user}]正在查看余票, 当前余票{ticket_num}张...')
# 购买车票
def buy(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
time.sleep(1)
if dic.get('ticket_num') > 0:
dic['ticket_num'] -= 1
with open('base_data', 'w', encoding='utf-8') as f1:
json.dump(dic, f1)
print(f'用户[{user}]抢票成功!')
else:
print(f'用户[{user}]抢票失败!')
# 开始抢票
def run(user, mutex):
# 上锁
mutex.acquire()
search(user)
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()
'''
用户[0]正在查看余票, 当前余票1张...
用户[0]抢票成功!
用户[3]正在查看余票, 当前余票0张...
用户[3]抢票失败!
用户[2]正在查看余票, 当前余票0张...
用户[2]抢票失败!
用户[4]正在查看余票, 当前余票0张...
用户[4]抢票失败!
用户[8]正在查看余票, 当前余票0张...
用户[8]抢票失败!
用户[6]正在查看余票, 当前余票0张...
用户[6]抢票失败!
用户[7]正在查看余票, 当前余票0张...
用户[7]抢票失败!
用户[5]正在查看余票, 当前余票0张...
用户[5]抢票失败!
用户[1]正在查看余票, 当前余票0张...
用户[1]抢票失败!
用户[9]正在查看余票, 当前余票0张...
用户[9]抢票失败!
'''
IPC
基本概念
- inter-process communication 进程间通信
- 进程间的数据是相互隔离的, 要想进行进程间的通信可以使用队列
队列
- 进程间通信的一种方式, 支持多进程传入和取出数据
- 遵循先进先出的原则
from multiprocessing import Queue
q = Queue(5) # 队列中最多存放5个数据
# 填入数据
q.put('数据1')
q.put('数据2')
q.put('数据3')
q.put('数据4')
q.put('数据5')
# q.put('数据6') # 数据填满了继续存放, 程序会被卡住
# 查看队列是否填满
print(q.full())
# 队列满了, 则会会报错
# q.put_nowait('数据6')
# 获取数据, 若队列中无数据可获取, 程序会卡住
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# 队列中没有, 则会报错
# print(q.get_nowait())
# 判断队列是否为空
print(q.empty())
'''
True
数据1
数据2
数据3
数据4
数据5
True
'''
生产者消费者模型
基本概念
- 生产者: 生产数据的
- 消费者: 使用数据
- 生产者消费者模型: 通过容器来解决生产者和消费者的之间的强耦合问题
代码实现
from multiprocessing import Process, Queue
import time
# 定义生产者
def producer(q):
for i in range(5):
data = f'包子{i}'
q.put(data)
print(f'生产了{data}')
time.sleep(0.1)
# 定义生产者
def consumer(q):
while True:
data = q.get()
print(f'吃了{data}')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
print('主')
'''
主
生产了包子0
吃了包子0
生产了包子1
吃了包子1
生产了包子2
吃了包子2
生产了包子3
吃了包子3
生产了包子4
吃了包子4
'''
线程
基本概念
- 进程是资源单位, 线程才是CPU的执行单位, 进行运算调度的最小单位
- 线程包含在进程之中, 是进程中的实际运作单位
- 线程开销要远小于进程, 可以节省内存资源
- 线程之间共享进程中的数据
- 线程pid为主进程pid
创建线程
from threading import Thread
import time
# 方式一
def task():
print('线程开启')
time.sleep(1)
print('线程结束')
if __name__ == '__main__':
t = Thread(target=task)
t.start()
# 方式二
class MyThread(Thread):
def run(self):
print('线程开启')
time.sleep(1)
print('线程结束')
if __name__ == '__main__':
t = MyThread()
t.start()
线程互斥锁
from threading import Thread, Lock
import time
n = 100
def task(i):
print(f'线程{i}启动...')
global n
temp = n
time.sleep(0.1)
n = temp - 1
print(n)
if __name__ == '__main__':
for i in range(10):
t = Thread(target=task, args=(i + 1,))
t.start()
'''
线程1启动...
线程2启动...
线程3启动...
线程4启动...
线程5启动...
线程6启动...
线程7启动...
线程8启动...
线程9启动...
线程10启动...
99
99
99
99
99
99
99
99
99
99
'''
from threading import Thread, Lock
import time
mutex = Lock()
n = 100
def task(i):
mutex.acquire()
print(f'线程{i}启动...')
global n
temp = n
time.sleep(0.1)
n = temp - 1
print(n)
mutex.release()
if __name__ == '__main__':
for i in range(10):
t = Thread(target=task, args=(i + 1,))
t.start()
'''
线程1启动...
99
线程2启动...
98
线程3启动...
97
线程4启动...
96
线程5启动...
95
线程6启动...
94
线程7启动...
93
线程8启动...
92
线程9启动...
91
线程10启动...
90
'''
Python3 并发编程2的更多相关文章
- Python3 并发编程4
目录 Event事件 线程池与进程池 基本概念 使用方法 和信号量的区别 协程(coroutine) 基本概念 实现方式 多线程爬取梨视频 Event事件 用来控制线程的执行 e.isSet()查看对 ...
- Python3 并发编程3
目录 GIL全局解释器锁 基本概念 多线程的作用 死锁现象 递归锁 信号量 线程队列 GIL全局解释器锁 基本概念 global interpreter lock 全局解释器锁 GIL不是Python ...
- Python3 并发编程小练习
实现基于TCP协议套接字,服务端实现接收客户端的连接并发 # server.py import socket from threading import Thread server = socket. ...
- Python3 并发编程1
目录 操作系统发展 穿孔卡片 批处理 多道技术(单核) 并发与并行 进程 程序与进程 进程调度 进程的三个状态 同步和异步 阻塞与非阻塞 僵尸进程与孤儿进程 守护进程 Python中的进程操作 Pro ...
- Python3 与 C# 并发编程之~ 进程篇
上次说了很多Linux下进程相关知识,这边不再复述,下面来说说Python的并发编程,如有错误欢迎提出- 如果遇到听不懂的可以看上一次的文章:https://www.cnblogs.com/dot ...
- Python3 与 C# 并发编程之~ 协程篇
3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...
- Python3 与 C# 并发编程之~进程先导篇
在线预览:http://github.lesschina.com/python/base/concurrency/1.并发编程-进程先导篇.html Python3 与 C# 并发编程之- 进程篇 ...
- Python3 与 C# 并发编程之~ 线程篇
2.线程篇¶ 在线预览:https://github.lesschina.com/python/base/concurrency/3.并发编程-线程篇.html 示例代码:https://gith ...
- asyncio:python3未来并发编程主流、充满野心的模块
介绍 asyncio是Python在3.5中正式引入的标准库,这是Python未来的并发编程的主流,非常重要的一个模块.有一个web框架叫sanic,就是基于asyncio,语法和flask类似,使用 ...
随机推荐
- (C#)WPF:LinearGradientBrush 线性渐变画刷和RadialGradientBrush 圆形渐变画刷
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/200 ...
- beyong Compare4解决30天的评估期结束
刚开始是删掉注册表的CacheId(无效) 1.在搜索栏中输入 regedit ,打开注册表2.删除项目CacheId :HKEY_CURRENT_USER\Software\Scooter Soft ...
- Nebula 架构剖析系列(二)图数据库的查询引擎设计
摘要 上文(存储篇)说到数据库重要的两部分为存储和计算,本篇内容为你解读图数据库 Nebula 在查询引擎 Query Engine 方面的设计实践. 在 Nebula 中,Query Engine ...
- Appium+python自动化(四十二)-Appium自动化测试框架综合实践- 寿终正寝完结篇(超详解)
1.简介 按照上一篇的计划,今天给小伙伴们分享执行测试用例,生成测试报告,以及自动化平台.今天这篇分享讲解完.Appium自动化测试框架就要告一段落了. 2.执行测试用例&报告生成 测试报告, ...
- class继承关键字extends和super
// 父类 class person { constructor (name,age) { this.name = name this.age = age } } class CheChinese e ...
- Orleans 3.0 为我们带来了什么
原文:https://devblogs.microsoft.com/dotnet/orleans-3-0/ 作者:Reuben Bond,Orleans首席软件开发工程师 翻译:艾心 这是一篇来自Or ...
- PostGIS mysql_fdw安装(Linux)
##本人在安装过程中,可能因为系统环境因素或是其他原因,参考网上的文章没有一篇是非常顺利的,所以自己总结一下. ##安装过程中非常坎坷,有些地方反复了好几次,弄的有点模糊,但模糊的地方在文中我会指出. ...
- Flex带CheckBox的Tree(修改ItemRenderer)
此文代码参考了:http://summerofthatyear-gmail-com.iteye.com/blog/326302 在此表示感谢! 前文提到了,实现带CheckBox的Tree有两种方法: ...
- Java基础知识总结之1.8新特性lambda表达式
函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的java.lang.Runnab ...
- 【论文阅读】Diverse Image-to-Image Translation via Disentangled Representations(ECCV2018 oral)
目录 相关链接 方法亮点 相关工作 方法细节 实验结果 总结与收获 参考文献 相关链接: 论文:https://arxiv.org/abs/1808.00948 代码:https://github.c ...