独立的进程内存空间
进程是独立的,互不干扰的独立内存空间
import multiprocessing
a = 1
def func():
global a
a=a+1
process = multiprocessing.Process(target=func)
process.start()
process.join()
print(a)
1
主进程a=1 , 子进程a=1 并修改为2
进程间通信的解决方案
共享的服务器进程空间
Manger对象的基本使用
进程间通信
from multiprocessing import Manager,Process
mgr = Manager() # 创建一个服务器进程 并返回与其通信的管理器
list_proxy = mgr.list() # 通过管理器在服务器进程中开辟一个列表空间,并返回一个代理
list_proxy.append('w')
def func(list_proxy):
list_proxy[0] = 'r'
print(list_proxy)
#将代理传给子进程 子进程可以通过这个代理 来操作共享空间 进行通信了
p = Process(target=func,args=(list_proxy,))
p.start()
p.join()
print(list_proxy)
print(type(list_proxy))
['w']
['r']
<class 'multiprocessing.managers.ListProxy'>
一般常用的空间类型是:
- mgr.list()
- mgr.dict()
- mgr.Queue()
Windows下python3的解释器
进程部分放到 if name == ‘main‘:下
from multiprocessing import Manager,Process
def func(list_proxy):
list_proxy[0] = 2
if __name__ == '__main__':
mgr = Manager() # 启动服务器进程
list_proxy = mgr.list() # 开辟一个列表空间
list_proxy.append(1)
p = Process(target=func,args=(list_proxy,))
p.start()
p.join()
print(list_proxy)
print(type(list_proxy))
线程间共享的全局变量
线程间全局变量的共享
线程属于同一个进程,因此它们之间共享内存区域,全局变量是公共的。
from threading import Thread
a = 1
def func():
global a
a = 2
mythread = Thread()
mythread.start()
print(a)
1
共享内存间存在竞争问题
from threading import Thread
a = 0
n = 1000
def add(n):
global a
for i in range(n):
a = a+1
def sub(n):
global a
for i in range(n):
a = a-1
mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))
mythread.start()
mythread1.start()
mythread.join()
mythread1.join()
print(a)
0
from threading import Thread
a = 0
n = 10000000
def add(n):
global a
for i in range(n):
a = a+1
def sub(n):
global a
for i in range(n):
a = a-1
mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))
mythread.start()
mythread1.start()
mythread.join()
mythread1.join()
print(a)
-707714
同步锁的基本概念
使用锁来控制共享资源的访问
lock.acquire() 加锁
lock.release() # 释放锁
from threading import Thread,Lock
a = 0
n = 10000000
lock = Lock() # 生成一把锁
def add(n):
global a
for i in range(n):
lock.acquire() # 加锁
a = a+1
lock.release() # 释放锁
def sub(n):
global a
for i in range(n):
lock.acquire() # 加锁
a = a-1
lock.acquire() # 释放锁
mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))
mythread.start()
mythread1.start()
mythread.join()
mythread1.join()
print(a)
0
with lock: # 加锁 自动释放
from threading import Thread,Lock
a = 0
n = 10000000
lock = Lock() # 生成一把锁
def add(n):
global a
for i in range(n):
with lock: # 加锁 自动释放
a = a+1
def sub(n):
global a
for i in range(n):
with lock: # 加锁 自动释放
a = a-1
mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))
mythread.start()
mythread1.start()
mythread.join()
mythread1.join()
print(a)
0
线程与进程安全的队列
队列的基本概念
一个入口,一个出口 先入先出(FIFO)
不需要加锁 不需要考虑竞争问题 队列里已经解决了 所以是安全队列
线程安全队列操作 queue.Queue
入队: put(item)
出队: get()
测试空: empty() # 近似
测试满: full() # 近似
队列长度: qsize() # 近似
任务结束: task_done()
等待完成: join()
import queue
q = queue.Queue(5) # 生成一个安全队列 只能放5个数据
print(q.qsize())
q.put('w') # 入队
print(q.qsize())
print(q.get()) # 出队
print(q.empty())
print(q.full())
0
1
w
True
False
进程安全队列操作 mgr.Queue
入队: put(item)
出队: get()
测试空: empty() # 近似
测试满: full() # 近似
测试满: full() # 近似
from multiprocessing import Manager
mgr = Manager()
a = mgr.Queue()
a.put('w')
print(a.get())
w
队列算公共资源嘛?
如果只是一个线程/进程在使用,那么它并不算公共资源。但是一旦多个线程/进程在同时使用,那么它就是一个公共资源。
我们是否需要对其加锁?
如果被当作公共资源使用,那么按理说是必须要加锁的。但是,线程安全或进程安全的队列中已经帮我们实现了锁。因此我们不需要再自己使用锁来同步。
生产者与消费者模型
生产者与消费者模型,本质上是把进程通信的问题分开考虑
生产者,只需要往队列里面丢东西(生产者不需要关心消费者)
消费者,只需要从队列里面拿东西(消费者也不需要关心生产者)
from threading import Thread
from queue import Queue
import random
class Producer(Thread):
def __init__(self,queue):
super().__init__()
self.queue = queue
def run(self):
while True:
item = random.randint(0,99)
self.queue.put(item)
print('生产者 生产了:%s' % (item))
class Concumer(Thread):
def __init__(self,queue):
super().__init__()
self.queue = queue
def run(self):
while True:
item = self.queue.get()
print('消费者 从队列中拿出%s' % (item))
queue = Queue(3)
concumer = Concumer(queue)
producer = Producer(queue)
concumer.start()
producer.start()
生产者 生产了:86
生产者 生产了:5
生产者 生产了:81
生产者 生产了:74
消费者 从队列中拿出86
生产者 生产了:64
消费者 从队列中拿出5
生产者 生产了:82
消费者 从队列中拿出81
生产者 生产了:70
消费者 从队列中拿出74
生产者 生产了:37
消费者 从队列中拿出64
。。。。。。
作业: 实现多进程的生产者与消费者模式
from multiprocessing import Process,Manager
import random
class Producer(Process):
def __init__(self, queue):
super().__init__()
self.queue = queue
def run(self):
while True:
item = random.randint(0, 99) # 假装生成一个数据
print('生产者 生产了:%s' % (item))
self.queue.put(item)
class Concumer(Process):
def __init__(self, queue):
super().__init__()
self.queue = queue
def run(self):
while True:
item = self.queue.get() # 从对队列中拿数据
print('消费者 从队列中拿出%s' % (item))
mgr = Manager() # 开启了用来通信的服务器进程 守护进程
queue = mgr.Queue(3)
producer = Producer(queue) # 生产者
producer.daemon = True
concumer = Concumer(queue) # 消费者
concumer.daemon = True # 在start之前开守护
concumer.start()
producer.start()
# 等待输入 让主进程不退出
input()
# 进程代码执行完退出的时候会杀死守护进程
# concumer.join() # 里面是while True 一直put
生产者 生产了:94
消费者 从队列中拿出94
生产者 生产了:31
消费者 从队列中拿出31
生产者 生产了:16
消费者 从队列中拿出16
生产者 生产了:7
消费者 从队列中拿出7