python_并发与通信
独立的进程内存空间与共享的服务器进程空间
知识点一: 进程间通信的限制
进程是独立的,互不干扰的独立内存空间
我们想不能修改变量
但是,深层次问题是,这个进程与那个进程完全失去了联系
import multiprocessing a = 1 # 全局变量 def func():
global a # 声明全局
a += 1 # 修改全局变量 p = multiprocessing.Process(target=func)
p.start()
p.join() # 等待子进程结束 print(a) # 结果是1 不同的进程
执行结果:
1
知识点二: 进程间通信的解决方案
1. 管理器负责与公共进程通信
2. 代理负责操作共享的空间
知识点三: Manger对象的基本使用
一般常用的空间类型是:
1. mgr.list()
2. mgr.dict()
3. mgr.Queue()
关于Queue()我们稍后演示
import multiprocessing
from multiprocessing import Manager
'''
常用的空间类型:
1、mgr.list() 列表
2、mgr.dict() 字典
3、mgr.Queue() 队列
''' mgr = Manager() # 创建一个服务器进程, 并返回与其通信的管理系
list_proxy = mgr.list() # 在服务器进程中开辟一个列表空间,并在主进程中返回一个代理
print(type(list_proxy)) # ListProxy def func(listData):
test = 'abcdef'
for i in test:
listData.append(i) p = multiprocessing.Process(target=func, args=(list_proxy,))
p.start()
p.join() # 等待进程 print(list_proxy)
线程间共享的全局变量与同步锁的基本概念
线程间全局变量的共享
提示!
因为线程属于同一个进程,因此它们之间共享内存区域。
因此全局变量是公共的。
import threading a = 1
def func():
global a
a = 2 t = threading.Thread(target=func)
t.start()
t.join() print(a) # 结果是2 一个进程下的多个线程
共享内存间存在竞争问题
提示!
如果1000000不能出现效果
可以继续在后面加0
import threading a = 1
n = 10000 def func(n):
global a
for i in range(n):
# print("加法:",i)
a += 1 def func2(n):
global a
for i in range(n):
# print("减法:",i)
a -= 1 t1 = threading.Thread(target=func, args=(1000000,)) # 如果是1000000 结果就不是1了, 因为共享内存空间存在竞争问题
t2 = threading.Thread(target=func2, args=(1000000,)) # 抢占资源,轮询调用的
t1.start()
t2.start()
t1.join()
t2.join() print(a) # 结果是2 一个进程下的多个线程
使用锁来控制共享资源的访问
方法一:
import threading
from threading import Lock
'''
线程锁: lock()
'''
lock = Lock() # 生成一个锁的实例 a = 1
n = 10000 def func(n):
global a
for i in range(n):
with lock:
a += 1 def func2(n):
global a
for i in range(n):
with lock:
a -= 1 t1 = threading.Thread(target=func, args=(1000000,))
t2 = threading.Thread(target=func2, args=(1000000,))
t1.start()
t2.start()
t1.join()
t2.join() print(a) # 结果是1
方法二:
import threading
from threading import Lock
'''
线程锁: lock()
'''
lock = Lock() # 生成一个锁的实例 a = 1
n = 10000 def func(n):
global a
for i in range(n):
lock.acquire() # 上锁
a += 1
lock.release() # 解锁 def func2(n):
global a
for i in range(n):
lock.acquire() # 上锁
a -= 1
lock.release() # 解锁 t1 = threading.Thread(target=func, args=(1000000,))
t2 = threading.Thread(target=func2, args=(1000000,))
t1.start()
t2.start()
t1.join()
t2.join() print(a) # 结果是1
线程与进程安全的队列
队列的基本概念
一个入口,一个出口
先入先出(FIFO)
queue.Queue
线程安全队列
操作一览
from queue import Queue
# 线程队列 q = Queue(5) # 队列里有5个长度,最大容纳,超出会溢出
q.put('a') # 入队
print("队列长度为: ",q.qsize()) # 队列长度
print("测试空: ", q.empty()) # 测试空 近似
print("测试结束: ", q.task_done()) # 任务结束
print("测试满: ", q.full()) # 测试满 近似
print("等待完成: ", q.join()) # 等待完成 print(q.get()) # 出队
结果:
队列长度为: 1
测试空: False
测试结束: None
测试满: False
等待完成: None
a
mgr.Queu
线程安全队列
操作一览
from multiprocessing import Manager
mgr = Manager()
qq = mgr.Queue()
qq.put('a') # 入队
print("测试满: ", qq.full()) # 测试满 近似
print("队列长度为: ",qq.qsize()) # 队列长度 近似
print("测试空: ", qq.empty()) # 测试空 近似 print("出队: ", qq.get())
结果:
测试满: False
队列长度为: 1
测试空: False
出队: a
其他问题解释
队列算公共资源嘛?
答:
如果只是一个线程/进程在使用,那么它并不算公共资源。
但是一旦多个线程/进程在同时使用,那么它就是一个公共资源。
我们是否需要对其加锁?
答:
如果被当作公共资源使用,那么按理说是必须要加锁的。
但是,线程安全或进程安全的队列中已经帮我们实现了锁。
因此我们不需要再自己使用锁来同步。
消费者与生产者模式
问题一: 什么是消费者与生产者模式?
所谓,生产者与消费者模型,其实是把一个需要进程通信的问题分开考虑
生产者,只需要往队列里面丢东西(生产者不需要关心消费者)
消费者,只需要从队列里面拿东西(消费者也不需要关心生产者)
问题二: 为什么需要消费者与生产者模式?
消费者与生产者模式的应用
—
Web服务器与Web框架之间的关系
问题三: 如何通过队列实现消费者与生产者模式?
多线程的消费者与生产者模式
方法一:
from threading import Thread
from queue import Queue
import random q = Queue(5) # 生成者
'''
只关心队列是否已满,没满则生成,满了就阻塞
'''
class Produce(Thread): def __init__(self, queue):
super().__init__() # 重写 init
self.queue = queue def run(self):
while True:
item = random.randint(0, 99)
self.queue.put(item) # 只要队列没满,向队列中存入数据
print("生产者-->已生产 %s, 并将其加入到了队列中" % item) # 消费者
'''
只关心队列是否为空。 不为空,则消费,为空则阻塞
'''
class Consumer(Thread):
def __init__(self, queue):
super().__init__()
self.queue = queue def run(self):
while True:
item = self.queue.get() # 只要队列不为空,就从队列取出数据
print("消费者:从队列中取出 %s " % item)
self.queue.task_done() p = Produce(q)
c = Consumer(q)
p.start()
c.start()
结果:
生产者-->已生产 28, 并将其加入到了队列中
生产者-->已生产 2, 并将其加入到了队列中
生产者-->已生产 64, 并将其加入到了队列中
生产者-->已生产 57, 并将其加入到了队列中
生产者-->已生产 94, 并将其加入到了队列中
生产者-->已生产 52, 并将其加入到了队列中
消费者:从队列中取出 28
生产者-->已生产 53, 并将其加入到了队列中
消费者:从队列中取出 2
生产者-->已生产 72, 并将其加入到了队列中
消费者:从队列中取出 64
消费者:从队列中取出 57
生产者-->已生产 29, 并将其加入到了队列中
消费者:从队列中取出 94
生产者-->已生产 46, 并将其加入到了队列中
生产者-->已生产 70, 并将其加入到了队列中
消费者:从队列中取出 52
生产者-->已生产 11, 并将其加入到了队列中
消费者:从队列中取出 53
生产者-->已生产 55, 并将其加入到了队列中
消费者:从队列中取出 72
生产者-->已生产 83, 并将其加入到了队列中
消费者:从队列中取出 29
生产者-->已生产 0, 并将其加入到了队列中
消费者:从队列中取出 46
生产者-->已生产 66, 并将其加入到了队列中
消费者:从队列中取出 70
生产者-->已生产 86, 并将其加入到了队列中
消费者:从队列中取出 11
生产者-->已生产 30, 并将其加入到了队列中
消费者:从队列中取出 55
生产者-->已生产 48, 并将其加入到了队列中
消费者:从队列中取出 83
生产者-->已生产 41, 并将其加入到了队列中
消费者:从队列中取出 0
生产者-->已生产 67, 并将其加入到了队列中
方法二:
from multiprocessing import Process, Manager
import random m = Manager()
q = m.Queue(5) # 生成者
'''
只关心队列是否已满,没满则生成,满了就阻塞
'''
class Produce(Process): def __init__(self, queue):
super().__init__() # 重写 init
self.queue = queue def run(self):
while True:
item = random.randint(0, 99)
self.queue.put(item) # 只要队列没满,向队列中存入数据
print("生产者-->已生产 %s, 并将其加入到了队列中" % item) # 消费者
'''
只关心队列是否为空。 不为空,则消费,为空则阻塞
'''
class Consumer(Process):
def __init__(self, queue):
super().__init__()
self.queue = queue def run(self):
while True:
item = self.queue.get() # 只要队列不为空,就从队列取出数据
print("消费者:从队列中取出 %s " % item)
self.queue.task_done() p = Produce(q)
c = Consumer(q)
p.start()
c.start()
p.join()
c.join()
结果:
生产者-->已生产 96, 并将其加入到了队列中
生产者-->已生产 53, 并将其加入到了队列中
生产者-->已生产 62, 并将其加入到了队列中
生产者-->已生产 21, 并将其加入到了队列中
生产者-->已生产 5, 并将其加入到了队列中
生产者-->已生产 83, 并将其加入到了队列中
消费者:从队列中取出 96
生产者-->已生产 54, 并将其加入到了队列中
消费者:从队列中取出 53
生产者-->已生产 99, 并将其加入到了队列中
消费者:从队列中取出 62
生产者-->已生产 93, 并将其加入到了队列中
消费者:从队列中取出 21
生产者-->已生产 58, 并将其加入到了队列中
总结完毕.
作者:含笑半步颠√
博客链接:https://www.cnblogs.com/lixy-88428977
声明:本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。如果您认为还不错,欢迎转载。转载与引用请注明作者及出处。
python_并发与通信的更多相关文章
- Python_编写UDP通信编解码类、文件的上传、远程执行命令、黏包
1.UDP通信编解码类 (1) 类 # ------------------UDP通信解码编码类------------------------ from socket import * class ...
- (转)C#SocketAsyncEventArgs实现高效能多并发TCPSocket通信
原文地址:http://freshflower.iteye.com/blog/2285272.http://freshflower.iteye.com/blog/2285286 一)服务器端 说到So ...
- C#SocketAsyncEventArgs实现高效能多并发TCPSocket通信 (服务器实现)
http://freshflower.iteye.com/blog/2285272 想着当初到处找不到相关资料来实现.net的Socket通信的痛苦与心酸, 于是将自己写的代码公布给大家, 让大家少走 ...
- python_并发编程——队列
1.队列 from multiprocessing import Queue q = Queue(5) #创建队列对象,队列大小为5,队列中只能存放5个元素 q.put(1) #往队列中添加元素 q. ...
- python_并发编程——进程池
1.进程池 from multiprocessing import Pool def func(n): for i in range(10): print(n+1) if __name__ == '_ ...
- 潭州课堂25班:Ph201805201 并发(通信) 第十三课 (课堂笔记)
from multiprocessing import Process # 有个 url 列表 ,有5个 url ,一次请求是1秒,5个5秒 # 要求1秒把 url 请求完, a = [] # 在进程 ...
- python_并发编程——数据共享
1.数据共享 实现进程之间的数据共享 from multiprocessing import Manager,Process class MyPro(Process): def __init__(se ...
- python_并发编程——管道
1.管道 from multiprocessing import Pipe conn1,conn2 = Pipe() #返回两个值 conn1.send('wdc') #发送 print(conn2. ...
- python_并发编程——消费者和生产者模型
消费者和生产者模型 from multiprocessing import Process,Queue import time import random class Producer(Process ...
随机推荐
- (持续更新) C# 面试技术点、常见SQL技术点 和 解决高并发的相关技术
这篇博客 持续更新. 方便小伙伴们学习与面试前的复习
- java并发编程(八) CAS & Unsafe & atomic
参考文档:https://www.cnblogs.com/xrq730/p/4976007.html CAS(Compare and Swap) 一个CAS方法包含三个参数CAS(V,E,N).V表示 ...
- SpringBoot整合MyBatis例子
1.pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...
- nodejs异常处理过程/获取nodejs异常类型/写一个eggjs异常处理中间件
前言 今天想写一下eggjs的自定义异常处理中间件,在写的时候遇到了问题,这个错误我捕获不到类型?? 处理过程,不喜欢看过程的朋友请直接看解决方法和总结 看一下是什么: 抛出的异常是检验失败异常Val ...
- linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】
本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...
- cesium地形瓦片(HeightMap)格式
目录 1.瓦片切分规则 2..terrain瓦片格式分析 参考资料: heightmap 1.0 Tile Map Service Specification 国内主要地图瓦片坐标系定义及计算原理 H ...
- 使用hdfs-mount挂载HDFS
目录 1.特性(计划)简介 2.构建程序 3.使用hdfs-mount挂载HDFS hdfs-mount是一个将HDFS挂载为本地Linux文件系统的工具,使用go语言开发,不依赖libdfs和jav ...
- KMS服务器激活
https://blog.csdn.net/weixin_42588262/article/details/81120403 http://kms.cangshui.net/ https://kms. ...
- 查找算法(6)--Block search--分块查找
1. 分块查找 (1)说明分块查找又称索引顺序查找,它是顺序查找的一种改进方法. (2)算法思想:将n个数据元素"按块有序"划分为m块(m ≤ n).每一块中的结点不必有序,但块与 ...
- Centos7安装完成后设定基本的网络配置
Centos7设定网络 新安装的centos7,网络默认是不启动的,需要人为的手工修改配置文件,在这里把这个过程简要的记录一下. 设定ip地址与mac地址自定义 [root@web ~]# cd /e ...