day29并发编程
day29并发编程
1、进程锁
一、使用锁维护执行顺序
代码:
from multiprocessing import Process,Lock
import os
import time
def task(i,lock):
# 开始上锁
lock.acquire()
print('第%s个:进程id号:%s进来了'%(i,os.getpid()))
time.sleep(3)
print('第%s个:进程ID号:%s走了'%(i,os.getpid()))
# 释放锁
lock.release()
if __name__ == '__main__':
lock = Lock() # 共用一把锁
for i in range(5):
p = Process(target=task,args=(i,lock))
p.start()
# 上面这种情况虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。
2、进程间数据隔离
一、进程之间数据是互不影响的
代码:
from multiprocessing import Process
n = 10
def task():
global n
n = 100
print('task:',n)
if __name__ == '__main__':
# task()
p =Process(target=task)
p.start()
print('main',n)
# 注:加上task()输出结果为main 10,task: 100
# 不加task()输出结果为main 10,task: 100
3、Queue队列的使用
一、方法介绍:
1.Queue([maxsize]):创建共享的进程队列。maxsize是队列允许的最大项数。如果不写参数的话。
2.q.get([block[,timeout]]):返回q中的一个项目。如果为空,此方法将造成堵塞,直到有可用项目为止。
3.q.get_nnowait():和q.get(False)方法一样,作用是控制堵塞:# q.put('my is handsome4', block=False)
4.q.put(item[,block[,timeout]]):将item放入队列
5.q.qsize():返回队列中目前项目的正确数量。
6.q.empty():如果队列里面放数据返回Fales,不放数据返回True,结果可能是不可靠的。
7.q.full():如果队列已满,返回True,结果可能是不可靠的
二、方法里的参数
1.如:q.get( [ block [ ,timeout ] ] ):返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 如果设置为False,将引发Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
2.用法如下:
代码:
from multiprocessing import Queue
if __name__ == '__main__':
q = Queue(3) # 拿到一个空队列的对象
q.put('my is handsome1') # 把数据放到队列中
q.put('my is handsome2')
q.put('my is handsome3')
q.put('my is handsome4', block=False) # block用于控制阻塞行为,如果设置为False,将引发Queue.Empty异常
q.put('my is handsome4', timeout=2) # 如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
q.put_nowait('my is handsome4') # 跟block方法一样的效果
print(q.get())
print(q.get()) # 返回q中的数据
print(q.get())
print(q.get(timeout=2)) # 也有队列的属性
print(q.get_nowait())
print(q.qsize()) # 返回队列中目前项目的正确数量
print(q.empty()) # 队列里面放数据返回Fales,不放数据返回True,结果可能是不可靠的
print(q.full()) # 队列已满,返回True,结果可能是不可靠的
4、解决进程间数据隔离问题
代码:
from multiprocessing import Process,Queue
def task(queue):
queue.put('hello') # 通过q.get()拿到的数据
print('hi') # 通过子进程得到的结果
if __name__ == '__main__':
q = Queue()
p =Process(target=task,args=(q, ))
p.start()
print(q.get()) # 通过主进程拿到“hello”数据
输出结果:hi ,hello
5、生产者消费者模型代码演示
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
5.1、为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
5.2、什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
5.3、代码演示
版本1:取完包子遇到阻塞,直到有可用项目为止
from multiprocessing import Process, Queue
import os
import time
# 版本1:取完包子遇到阻塞,直到有可用项目为止
def producer(queue):
for i in range(5):
data = ('%s:蒸了第%s个包子' % (os.getpid(), i))
print(data)
queue.put(data) # 把数据放入队列
def consumer(queue):
while True:
data = queue.get()
print(data)
if __name__ == '__main__':
q = Queue()
p = Process(target=producer, args=(q,))
p.start()
p1 = Process(target=consumer, args=(q,))
p1.start()
版本2:
def producer(queue):
for i in range(5):
data = ('%s:蒸了第%s个包子' % (os.getpid(), i))
print(data)
queue.put(data) # 把数据放入队列
queue.put(None)
def consumer(queue):
while True:
data = queue.get()
if not data:break
time.sleep(1)
print(data)
if __name__ == '__main__':
q = Queue()
p = Process(target=producer, args=(q,))
p.start()
p1 = Process(target=consumer, args=(q,))
p1.start()
版本3: 多生产者,少消费者
def producer(queue,food):
for i in range(5):
data = ('%s:生产了第%s个%s' % (os.getpid(), i,food))
# print(data)
queue.put(data) # 把数据放入队列
def consumer(queue):
while True:
data = queue.get()
if not data:break
time.sleep(0.2)
print(data)
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,'馒头'))
p2 = Process(target=producer, args=(q,'花卷'))
p3 = Process(target=producer, args=(q,'烧麦'))
p1.start()
p2.start()
p3.start()
p4 = Process(target=consumer, args=(q,))
p5 = Process(target=consumer, args=(q,))
p4.start()
p5.start()
p1.join() # 加上join
p2.join() # 加上join
p3.join() # 加上join
q.put(None) # 这里放几个取决于消费者有几个
q.put(None)
print('=====>')
版本四:最终版本:消费者多,生产者少
def producer(queue,food):
for i in range(5):
data = ('%s:生产了第%s个%s' % (os.getpid(), i,food))
# print(data)
queue.put('第%s个%s'%(i,food)) # 把数据放入队列
def consumer(queue,name):
while True:
try:
data = queue.get(timeout=3)
if not data:break
time.sleep(0.2)
print('消费者:%s,消费了:%s'%(name,data))
except Exception as e:
print(e)
break
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,'馒头'))
p2 = Process(target=producer, args=(q,'花卷'))
p3 = Process(target=producer, args=(q,'烧麦'))
p1.start()
p2.start()
p3.start()
p4 = Process(target=consumer, args=(q,'迪迦'))
p5 = Process(target=consumer, args=(q,'琦玉'))
p6 = Process(target=consumer, args=(q,'悟空'))
p7 = Process(target=consumer, args=(q,'路飞'))
p4.start()
p5.start()
p6.start()
p7.start()
p1.join() # 加上join
p2.join() # 加上join
p3.join() # 加上join
q.put(None) # 这里放几个取决于消费者有几个
q.put(None)
print('=====>')
day29并发编程的更多相关文章
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- 伪共享(false sharing),并发编程无声的性能杀手
在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...
- 【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 【Java并发编程实战】-----“J.U.C”:CLH队列锁
在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...
- 【Java并发编程实战】-----“J.U.C”:Exchanger
前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...
- 【Java并发编程实战】-----“J.U.C”:CountDownlatch
上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...
- 【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
随机推荐
- 我的笔记本电脑瞬间扩大一个T的容量!
前言 不知道有多少人在家里搭建中央存储设备的,也就是NAS.这个东西在我日常生活中,存储了大量的个人资料,家人们的照片,技术的资料,还有各种高清影视剧.搭配公网的IP,可以真正做到,任何时候任何地点的 ...
- 修改 oracle 数据库的 sys 账号密码,ERROR at line 1: ORA-01034: ORACLE not available
挺久没有登录的 oracle 数据库,因为公司要求加固密码,登录后修改失败 1.启动数据库的同时启动控制文件.数据文件,提示:cannot mount database in EXCLUSIVE mo ...
- Android App隐私合规检测辅助工具(Camille)
Camille Android App隐私合规检测辅助工具,项目仓库:https://github.com/zhengjim/camille 简介 现如今APP隐私合规十分重要,各监管部门不断开展AP ...
- 【完美解决】IDEA 中 Maven 报错 Cannot resolve xxx 和 Maven 中 Dependencies 报红/报错。
目录 前提 场景 解决办法 1.首先,清除缓存,点击之后重启IDEA. 2.关闭IDEA,打开项目文件夹 3.重新打开 IDEA,找到右边的 Maven 4.解决 Maven 中 Dependenci ...
- 攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup
攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup 题目介绍 题目考点 PHP代码审计 git源码泄露 Writeup 进入题目,点击一番,发现可能出现git ...
- C++ 重载、重写、重定义的区别
C++ 中 重载.重写.重定义的区别 重载(overload) 定义: 在同一个作用域内,两函数的函数名相同, 参数不相同(可以是参数类型不同或者是参数个数不同), 那么就说这两个 函数重载. 分类: ...
- 日志框架-logtube
Logtube 是什么 logtube 框架是基于 slf4j的一个日志框架封装, 源码地址: https://github.com/logtube 基于 SLF4J框架, 扩展了日志输出格式 (兼容 ...
- 4.ASCII码排序
描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个字符. 输入 第一行输入一个数N,表示有N组测试数据.后面的N行输入多组数据,每组输入数据都是占一行,有三个字符组成,之 ...
- vue.js3 学习笔记 (一)——mixin 混入
vue 2 中采用选项式API.如:data.methods.watch.computed以及生命周期钩子函数等等. mixin 混入,提供了一种非常灵活的方式,来分发 vue 组件中的可复用功能,一 ...
- Spark面试题(七)——Spark程序开发调优
Spark系列面试题 Spark面试题(一) Spark面试题(二) Spark面试题(三) Spark面试题(四) Spark面试题(五)--数据倾斜调优 Spark面试题(六)--Spark资源调 ...