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中是这么 ...
随机推荐
- python doc os 参考
os --- 操作系统接口模块 源代码: Lib/os.py 该模块提供了一些方便使用操作系统相关功能的函数. 如果你是想读写一个文件,请参阅 open(),如果你想操作路径,请参阅 os.path ...
- hdu 2955 Robberies(背包DP)
题意: 小偷去抢银行,他母亲很担心. 他母亲希望他被抓的概率真不超过P.小偷打算去抢N个银行,每个银行有两个值Mi.Pi,Mi:抢第i个银行所获得的财产 Pi:抢第i个银行被抓的概率 求最多能抢得多少 ...
- PicGo插件
前言:主要介绍PicGo插件,这里的图床上传软件是PicGo-Core,使用命令行操作 PicGo_Path:自己的PicGo安装路径,如果通过Typora一般安装位置位于 C:\Users\自己的主 ...
- Vue3.x 关于组件的那些变化(新手必看篇)
一.组件内的 data 为什么总是函数形式? 我们试着先做一个计数器案例,把 data 的返回形式修改成一个对象.具体的代码如下: <template> <div> <b ...
- vue中main.js配置后端请求地址
Vue.config.productionTip = false; axios.defaults.baseURL = 'http://127.0.0.1:8003/';//后端开发环境地址 // ax ...
- go 集合
p.p1 { margin: 0; font: 12px ".PingFang SC"; color: rgba(69, 69, 69, 1) } span.s1 { font: ...
- CobaltStrike上线Linux
为获得最佳的阅读体验,请访问我的个人主页: https://xzajyjs.cn/ 在红蓝对抗中,我们常需要对目标进行长时间的控制,cobaltstrike原生对于上线windows比较轻松友好,但如 ...
- WPF进阶技巧和实战09-事件(2-多点触控)
多点触控输入 多点触控输入和传统的基于比的输入的区别是多点触控识别手势,用户可以移动多根手指以执行常见的操作,放大,旋转,拖动等. 多点触控的输入层次 WPF允许使用键盘和鼠标的高层次输入(例如单击和 ...
- (一)初识MySQL
JavaEE:企业级Java开发 Web 前端(页面:展示,数据) 后台(连接点,连接数据库JDBC,链接前端(控制,控制视图跳转和给前端传递数据)) 数据库(存数据,Txt,Excel,word) ...
- 菜鸡的Java笔记 - java 常用类库
CommonClassLibrary 常用类库 定时调度 定时调度指的是每到一个时刻,都会自动的产生某些特定的操作形式 con ...