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. 连续子序列的最大和 牛客网 剑指Offer

    连续子序列的最大和 牛客网 剑指Offer 题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量 ...

  2. JMeter学习笔记--工具简单介绍

    一.JMeter 介绍 Apache JMeter是纯JAVA桌面应用程序,被设计为用于测试客户端/服务端结构的软件(例如web应用程序).它可以用来测试静态和动态资源的性能,例如:静态文件,Java ...

  3. idea查看方法在哪里被调用

    方法一 选中方法名,右键选择Find Usages 方法二 选中方法快捷键ctrl + alt + h查看Hierarchy Callers

  4. vue中this.$set的用法

    之前了解这个方法的时候,感觉这一辈子也用不到这个方法,因为当时没有应用场景,但是还真有用的时候,我相信你们也有用到时候. 从三个方面给大家说一下这个this.$set: 1.this.$set实现什么 ...

  5. RabbitMQ保证消息的顺序性

    当我们的系统中引入了MQ之后,不得不考虑的一个问题是如何保证消息的顺序性,这是一个至关重要的事情,如果顺序错乱了,就会导致数据的不一致.       比如:业务场景是这样的:我们需要根据mysql的b ...

  6. MySQL基础语句(MySQL内置函数 )

    MySQL 字符串函数 函数 描述 实例 ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码. 返回 CustomerName 字段第一个字母的 ASCII 码: SELECT ASCI ...

  7. Django 小实例S1 简易学生选课管理系统 8 CSS样式优化

    Django 小实例S1 简易学生选课管理系统 第8节--CSS样式优化 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 前面的几节下来,用户模块基 ...

  8. laravel DB 类库

    DB 类操作数据库    基本用法: DB::table('tableName'); 获取操作tableName 表        增加信息        对数据库中的某个表增加数据主要有两个函数可以 ...

  9. Spark 安装部署与快速上手

    Spark 介绍 核心概念 Spark 是 UC Berkeley AMP lab 开发的一个集群计算的框架,类似于 Hadoop,但有很多的区别. 最大的优化是让计算任务的中间结果可以存储在内存中, ...

  10. SpringCloud升级之路2020.0.x版-40. spock 单元测试封装的 WebClient(上)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们来测试下前面封装好的 WebClient,这里开始,我们使用 spock 编写 gro ...