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并发编程的更多相关文章

  1. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  2. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  3. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  4. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  5. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  6. 【Java并发编程实战】-----“J.U.C”:CLH队列锁

    在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...

  7. 【Java并发编程实战】-----“J.U.C”:Exchanger

    前面介绍了三个同步辅助类:CyclicBarrier.Barrier.Phaser,这篇博客介绍最后一个:Exchanger.JDK API是这样介绍的:可以在对中对元素进行配对和交换的线程的同步点. ...

  8. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  9. 【Java并发编程实战】-----“J.U.C”:CyclicBarrier

    在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...

随机推荐

  1. VCS常用仿真选项开关及步骤总结

    转自:https://blog.csdn.net/bcs_01/article/details/79803304 转自:https://blog.csdn.net/wonder_coole/artic ...

  2. stop: Job failed while stopping start: Job is already running: networking eth0 not configured

    再给ubuntu系统重启网络服务的时候出现失败,"stop: Job failed while stopping start: Job is already running: network ...

  3. minimum-depth-of-binary-tree leetcode C++

    Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the short ...

  4. [WPF] 使用三种方式实现弧形进度条

    1. 需求 前天看到有人问弧形进度条怎么做,我模仿了一下,成果如下图所示: 当时我第一反应是可以用 Microsoft.Toolkit.Uwp.UI.Controls 里的 RadialGauge 实 ...

  5. CLion 2021.2 debug报错 process exited with status -1 (attach failed (Not allowed to attach to process.

    Clion 升级 2021.2 版本后 debug 报错: process exited with status -1 (attach failed (Not allowed to attach to ...

  6. /etc/passwd 和 /etc/shadows 详解

    linux操作系统上的用户如果需要登录主机,当其输入用户名和密码之后: 首先在/etc/passwd文件中查找是否有你的账号,如果没有无法登录,如果有的话将该用户的UID和GID读出来,此外将此用户的 ...

  7. etcd原理详解代码剖析

    1 架构 从etcd的架构图中我们可以看到,etcd主要分为四个部分. HTTP Server: 用于处理用户发送的API请求以及其它etcd节点的同步与心跳信息请求. Store:用于处理etcd支 ...

  8. C#中base 和this

    [意义] this:指当前类,this调用当前类的属性,方法,包括构造函数的方法,继承本类的构造函数 base:指当前类的父类,可调用父类的非私有属性,方法,继承父类的构造函数括号里的参数 [用处] ...

  9. [bzoj1079]着色方案

    由于最终的染色只与ci为几的个数有关,因此定义状态f[a][b][c][d][e][p]表示有a个ci=1,b个ci=2,--,有e个ci=5,上一次选择了ci=p的.状态的转移:发现p会让p-1少选 ...

  10. Dapr初体验之服务调用

    初次理解服务调用 在微服务中,有一个难点就是:如果你想使用各个服务组件,你就得知道不同服务的地址和端口,也就是服务发现. 在传统应用我们是怎么做的?就是在web项目里配置上api地址,如下: 在一个w ...