一.锁 Lock

from multiprocessing import Process,Lock
1.Lock基本用法

上锁和解锁是一对,只上锁不解锁会发生死锁现象(代码阻塞,不往下执行了)
互斥锁:互斥锁是进程之间的互相排斥,谁先抢到这个锁资源就先使用,后抢到后使用

# 创建一把锁
lock = Lock()
# 上锁
lock.acquire()
# 连续上锁不解锁是死锁
# lock.acquire()  # errorprint("厕所")# 解锁
lock.release()
print("执行程序...")
2.模拟12306抢票软件
import json,time
# 读写数据库中的票数
def wr_info(sign, dic=None):if sign == "r":with open("ticket", mode="r", encoding="utf-8") as fp:dic = json.load(fp)return dicelif sign == "w":with open("ticket", mode="w", encoding="utf-8") as fp:json.dump(dic, fp)# res = wr_info("r")
# print(res)
# dic = {"count": 0}
# wr_info("w", dic)# 抢票方法
def get_ticket(person):# 获取数据库中的实际的票数dic = wr_info("r")print(dic)# 模拟一下网络延迟time.sleep(0.5)# 判断票数if dic["count"] > 0:print("%s抢到票了" % (person))dic["count"] -= 1wr_info("w", dic)else:print("%s没有抢到这张票" % (person))def run(person, lock):# 查看剩余票数dic = wr_info("r")print("%s 查询票数: %s" % (person, dic["count"]))# 上锁lock.acquire()# 开始抢票get_ticket(person)lock.release()if __name__ == '__main__':lock = Lock()lst = ["李志辉", "宋云杰", "高云峰", "戈隆", "孙致和", "李虎玲", "袁伟倬", "刘鑫炜", "马生平", "刘鑫"]for i in lst:p = Process(target=run, args=(i, lock))p.start()

创建进程的时候,仍然是异步并发,在执行到上锁时,多个进程之间变成了同步程序.
先来的先上锁,先执行,后来的进程后上锁,后执行

二.信号量 Semaphore

本质上就是锁,只不过可以控制上锁的数量

from multiprocessing import Semaphore,Process
import time,random
"""
sem = Semaphore(4)
sem.acquire()
# sem.acquire()
# sem.acquire()
# sem.acquire()
# sem.acquire()  # 上第五把锁出现死锁状态
print("执行响应的操作")
sem.release()
"""
def ktv(person, sem):sem.acquire()print("%s进入了ktv,正在唱歌" % (person))# 开始唱歌,唱一段时间time.sleep(random.randrange(3, 7))  # 3 4 5 6print("%s离开了ktv,唱完了" % (person))sem.release()if __name__ == '__main__':sem = Semaphore(4)lst = ["毛洪磊","郭凯","刘子涛","宋云杰","马生平","李亚","刘彩霞","张捷","王盼盼","徐艳伟"]for i in lst:p = Process(target=ktv, args=(i, sem))p.start()

总结:
Semaphore 可以设置上锁的数量
同一时间最多允许几个进程上锁
创建进程的时候,是异步并发
执行任务的时候,遇到锁会变成同步程序

三.事件(Event)

阻塞事件:
e = Event()生成事件对象e
e.wait()动态给程序加阻塞,程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
如果是True 不加阻塞
如果是False 加阻塞

控制这个属性的值
set()方法 将这个属性的值改为True
clear()方法 将这个属性的值改为False
is_set()方法 判断当前的属性是否是True(默认上来是False)

1.基本语法
from multiprocessing import Process,Event
import time,random
# 1.
e = Event()
print(e.is_set())
e.wait()
print("程序运行中...")
2.
e = Event()
e.set()  # 将内部成员属性值由False -> True
print(e.is_set())
e.wait()
print("程序运行中...")e.clear()  # 将内部成员属性由True -> False
e.wait()
print("成员运行中2")
3.
e = Event()
# wait参数 可以写时间 wait(3) 代表最多等待3秒钟
e.wait(3)
print("程序运行中3...")
2.模拟经典红绿灯效果
def traffic_light(e):print("红灯亮")while True:if e.is_set():# 绿灯状态,亮1秒钟time.sleep(1)print("红灯亮")e.clear()else:# 红灯状态,亮1秒钟time.sleep(1)print("绿灯亮")e.set()# e = Event()
# traffic_light(e)def car(e, i):# not False => True => 目前是红灯,小车在等待if not e.is_set():print("car%s 在等待" % (i))# 加阻塞e.wait()print("car%s 通行了" % (i))
# 不关红绿灯,一直跑
if __name__ == '__main__':e = Event()# 创建交通灯对象p1 = Process(target=traffic_light, args=(e,))p1.start()# 创建车对象for i in range(1, 21):time.sleep(random.randrange(0, 2))  # 0 1p2 = Process(target=car, args=(e, i))p2.start()
# 当所有小车都跑完之后,把红绿灯收拾起来,省电
if __name__ == '__main__':lst = []e = Event()# 创建交通灯对象p1 = Process(target=traffic_light, args=(e,))# 设置红绿灯为守护进程p1.daemon = Truep1.start()# 创建车对象for i in range(1, 21):time.sleep(random.randrange(0, 2))  # 0 1p2 = Process(target=car, args=(e, i))p2.start()lst.append(p2)# 让所有的小车都通行之后,再结束交通灯for i in lst:i.join()print("程序结束")

四.进程队列

from multiprocessing import Process,Queue
import queue

队列特点:先进先出,后进后出

1.put 往队列中放值
q = Queue()
q.put(100)
q.put(101)
q.put(102)
2.get 从队列中取值
res = q.get()
print(res)
res = q.get()
print(res)
# res = q.get()
# print(res)
3.队列中如果已经没有数据了,再调用get会发生阻塞
"""
res = q.get()
print(res)
"""
4.get_nowait 存在系统系统兼容性问题[Windows]好用 [Linux]不好用 不推荐
res = q.get_nowait()
print(res)
try:res = q.get_nowait()print(res)
except queue.Empty:pass
5.设置队列的长度
"""设置队列长度最多存放4个元素"""
"""
print("======")
q2 = Queue(4)
q2.put(200)
q2.put(201)
q2.put(202)
# q2.put(203)
# 如果超出了队列的指定长度,再继续存值会出现阻塞现象
# q2.put(204)
6.put_nowait() 非阻塞版本的put,超出长度后,直接报错
q2.put_nowait(204)
try:q2.put_nowait(205)
except queue.Full:pass

五.进程之间的数据共享

def func(q3):# 2.子进程获取数据res = q3.get()print(res)# 3.子进程存数据q3.put("马生平")if __name__ == '__main__':q3 = Queue()p = Process(target=func, args=(q3,))p.start()# 1.主进程加数据q3.put("王凡")# 为了等待子进程把数据放到队列中,需要加joinp.join()# 4.主进程获取数据res = q3.get()print(res)print("主程序结束...")

六.生产者 和 消费者 模型

爬虫例子:
1号进程负责爬取页面中所有想要的数据
2号进程负责把内容取出来,按照规则进行匹配,扣取关键字

1号进程可以理解成生产者
2号进程可以理解成消费者

理想的生产者和消费者模型中,彼此的速度相对均匀

从程序上来讲:
生产者负责存储数据(put)
消费者负责获取数据(get)

from multiprocessing import Process,Queue
import time,random
1.基本模型
# 消费者模型
def consumer(q, name):while True:food = q.get()time.sleep(random.uniform(0.1, 1))print("%s 吃了一个%s" % (name, food))# 生产者模型
def producer(q, name, food):for i in range(5):time.sleep(random.uniform(0.1, 1))# 打印生产的数据print("%s 生产了 %s%s" % (name, food, i))# 存储生产的数据q.put(food + str(i))if __name__ == '__main__':q = Queue()# 消费者p1 = Process(target=consumer, args=(q, "宋云杰"))# 生产者p2 = Process(target=producer, args=(q, "马生平", "黄瓜"))p1.start()p2.start()
2.优化版
# 消费者模型
def consumer(q, name):while True:food = q.get()if food is None:breaktime.sleep(random.uniform(0.1, 1))print("%s 吃了一个%s" % (name, food))# 生产者模型
def producer(q, name, food):for i in range(5):time.sleep(random.uniform(0.1, 1))# 打印生产的模型print("%s 生产了 %s%s" % (name, food, i))# 存储生产的数据q.put(food + str(i))if __name__ == '__main__':q = Queue()p1 = Process(target=consumer, args=(q, "宋云杰"))# 生产者p2 = Process(target=producer, args=(q, "马生平", "黄瓜"))p1.start()p2.start()# 在生产者生产完所有数据之后,在队列的末尾添加一个Nonep2.join()q.put(None)

一个生产者和一个消费者,最后队列中加一个None
多个生产者和多个消费者,最后队列中加多个None

七.JoinableQueue

from multiprocessing import Process,JoinableQueue
import time,random

put 存储
get 获取
task_done
join

task_done 和 join 配合使用的
队列中 1 2 3 4 5
put 一次 内部的队列计数器减1
join一次 通过task_done让队列计数器减1
join函数,会根据队列计数器来判断是阻塞还是放行
队列计数器 = 0, 意味着放行
队列计数器 != 0, 意味着阻塞

1.基本语法
jq = JoinableQueue()
jq.put("a")
print(jq.get())
# 通过task_done让队列计数器减1
jq.task_done()
jq.join()
print("finish")
2.改造生产者和消费者模型
def consumer(q, name):while True:food = q.get()time.sleep(random.uniform(0.1, 1))print("%s 吃了一个%s" % (name, food))# 当队列计数器减到0时,意味着进程队列中的数据消费完毕q.task_done()# 生产者模型
def produce(q, name, food):for i in range(5):time.sleep(random.uniform(0.1, 1))# 打印生产的数据print("%s 生产了 %s%s" % (name, food, i))# 存储生产的数据q.put(food + str(i))if __name__ == '__main__':q = JoinableQueue()# 消费者p1 = Process(target=consumer, args=(q, "宋云杰"))# 生产者p2 = Process(target=produce, args=(q, "马生平","黄瓜"))# 设置p1消费者为守护进程p1.daemon = Truep1.start()p2.start()# 把所有生产者的数据存放到进程队列中p2.join()# 为了保证消费者能够消费完所有数据,加上队列.join# 当队列计数器减到0,放行,不在阻塞,程序彻底结束q.join()print("程序结束...")

0818Python总结-lock,Semaphore,event,Queue,生产者和消费者模型,JoinableQueue相关推荐

  1. Linux系统编程:使用semaphore信号量和mutex互斥量实现多个生产者和消费者模型

    代码实现 如题,使用semaphore信号量和mutex互斥量实现多个生产者和消费者模型.本来是想只用信号量实现生产者消费者模型的,但是发现 只能在一个生产者和一个消费者之间,要在多个生产者和消费者模 ...

  2. python生产和消费模型_python queue和生产者和消费者模型

    queue队列 当必须安全地在多个线程之间交换信息时,队列在线程编程中特别有用. classqueue.Queue(maxsize=0) #先入先出classqueue.LifoQueue(maxsi ...

  3. day034 锁,信号量,事件,队列,子进程与子进程通信,生产者消费者模型,joinableQueue...

    进程锁 #加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全. 虽然可以用文件共享数据实现进程间通信,但问题是: 1 ...

  4. python 进程间同步_python之路29 -- 多进程与进程同步(进程锁、信号量、事件)与进程间的通讯(队列和管道、生产者与消费者模型)与进程池...

    所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了.至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠 ...

  5. Linux系统编程---17(条件变量及其函数,生产者消费者条件变量模型,生产者与消费者模型(线程安全队列),条件变量优点,信号量及其主要函数,信号量与条件变量的区别,)

    条件变量 条件变量本身不是锁!但它也可以造成线程阻塞.通常与互斥锁配合使用.给多线程提供一个会合的场所. 主要应用函数: pthread_cond_init 函数 pthread_cond_destr ...

  6. Linux 生产者与消费者模型C++实现

    生产者与消费者模型 本篇博客代码实现都是在linux环境下跑的 通过条件变量实现 应用场景:针对大量数据的产生与处理的场景 生产与处理是放到不同执行流中完成的,中间会增加一个数据缓冲区,作为中间的数据 ...

  7. 开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型...

    开启子进程的两种方式 # # # 方式一: # from multiprocessing import Process # import time # # def task(x): # print(' ...

  8. C++实现生产者和消费者模型

    C++实现生产者和消费者模型 C++实现生产者和消费者模型 1.实现细节 2.单生产者-单消费者模型 3.单生产者-多消费者模型 4.多生产者-单消费者模型 5.多生产者-多消费者模型 参考 C++实 ...

  9. c/c++:线程同步(互斥锁、死锁、读写锁、条件变量、生产者和消费者模型、信号量)

    目录 1. 概念 2. 互斥锁 3. 死锁 4. 读写锁 5. 条件变量 5.1 生产者和消费者模型 6. 信号量 1. 概念 线程同步: > 当有一个线程在对内存进行操作时,其他线程都不可以对 ...

最新文章

  1. 图片加载框架Glide的简单使用
  2. python2与python3在absolute import的区别
  3. 进程和线程基础知识(已经是最详细的啦)
  4. 关于处理小数点位数的几个oracle函数
  5. Teams Tab的Single Sign-On
  6. 2014 网选 5024 Wang Xifeng's Little Plot
  7. Python—语法基础(8) 分支、循环结构
  8. 金数据一个不错的调查平台
  9. vue项目中遇到的问题总结
  10. speak 计算机英语作文,跪求一篇英语作文 题目:论计算机的优缺点
  11. 两轮差速驱动机器人运动模型及应用分析(图片版)
  12. modbus发送接收_自己编写MODBUS协议代码所踩过的坑
  13. 南京邮电大学-IP网络技术重难点突破(江凌云老师课程)
  14. 判断一个数是否为质数(素数)的4种方法
  15. 第十一期_MSF 后渗透《Metasploit Unleashed Simplified Chinese version(Metasploit官方文档教程中文版)》
  16. 接口测试之postman
  17. 零基础如何开始学素描?
  18. matlab 怎么解ode方程,Matlab解微分方程(ODE+PDE).pdf
  19. N个鸡蛋放到M个篮子中
  20. 解决React Navigation goBack()无效

热门文章

  1. Direct exchange
  2. 用BDP个人版制作人口金字塔
  3. PyCharm 社区版首次上传代码到GitHub和新增代码上传到GitHub(超详细)
  4. C语言关键字之voliate
  5. 地方政府隐性债务的累积
  6. eclipse+jsp+servlet+sqlserver+tomcat实现增删改查的一个小项目(超详细教程)
  7. C++图像处理 -- 图像颜色混合(上)
  8. Linux装docker + rancher
  9. 【软件工程】软件工程知识点提纲7
  10. 【原创】Android学习appwidget制作一个桌面相册幻灯片