并发通信
一、进程相互通信
1、通信隔离
import multiprocessing
var = 10
def func():
global var
var += 1
print(var)
return var
p1 = multiprocessing.Process(target=func)
p1.start()
p1.join()
print(var)
进程间的隔离
可以看到在不同进程中,即使声明了去全局变量,也还是没有作用
管理器用来通信,代理来操作
2、代码实现
import multiprocessing
mg = multiprocessing.Manager() # 创建一个服务器进程,并返回与期通信的管理器
def func(dict_var):
dict_var.update({'a': 1,'b': 2})
dict_var = mg.dict() # 在进程中开辟一个字典空间,并在主程序中返回一个代理
p1 = multiprocessing.Process(target=func,args=(dict_var,))
p1.start()
p1.join()
print(dict_var) # 执行完之后,字典不再为空
Manger
Manger
是进程间通信的常用解决方案,通过公共空间来实现进程间的通信
二、线程的通信
1、线程共享
import threading
var = 123
def func():
global var
var += 1
return var
t = threading.Thread(target=func)
t.start()
t.join()
print(var)
线程共享空间
对于线程而言,它们始终在一个进程当中,因此共享同一个内存空间,因此可以访问主进程中的数据
import threading
var = 1
def f1():
global var
for i in range(1000000): # 如果不能出现效果可以增加次数
var += i
def f2():
global var
for i in range(1000000):
var -= i
t1 = threading.Thread(target=f1)
t1.start()
t2 = threading.Thread(target=f2)
t2.start()
t1.join()
t2.join()
print(var)
第一次
第二次
线程争夺
这个时候出现资源错误,因为CPU计算是多条指令,组合运行的,所以在运行过程中如果插入其他指令,就会造成不可预见的结果
2、互斥锁
互斥锁
对于特殊资源,可以加上锁,来保护资源,确保每次操作的完整性。
import threading
var = 1
lock = threading.Lock()
def f1():
global var
for i in range(1000000): # 如果不能出现效果可以增加次数
lock.acquire() # 操作前加上锁
var += i
lock.release() # 操作完解除锁
def f2():
global var
for i in range(1000000):
lock.acquire() # 操作前加上锁
var -= i
lock.release() # 操作完解除锁
t1 = threading.Thread(target=f1)
t1.start()
t2 = threading.Thread(target=f2)
t2.start()
t1.join()
t2.join()
print(var)
三、队列
1、队列
先进先出
2、队列操作
入队:put(item)
出队:get()
测试空:empty()近似值
测试满:full()近似值
队列长度:qsize()近似值
任务结束:task_done()线程使用
等待完成:join()线程使用
import queue
q = queue.Queue()
q.put('a')
print(q.get())
q1 = queue.Queue(3) # 数字三代表队列长度
四、生产者与消费者模型
1、基本概念
2、实际应用-web服务器
3、代码实现
import threading
import queue
import time
q = queue.Queue(4)
# 生产者
class Producer(threading.Thread):
def __init__(self,queue):
super().__init__() #使用父类的初始化方法使实例对象成为线程对象
self.queue = queue
def run(self):
# 生产者逻辑 不需要管消费者 只需要往队列中put我的问题即可
import random
while True:
time.sleep(1)
x = random.randint(0,100)
self.queue.put(x)
print(f'生产者生产了数据{x}')
# 消费者
class Consumer(threading.Thread):
def __init__(self,queue):
super().__init__() #使用父类的初始化方法使实例对象成为线程对象
self.queue = queue
def run(self):
# 消费者逻辑 不需要管生产者 只需要把队列中的问题get出来解决即可
while True:
time.sleep(1)
data = self.queue.get()
print(f'消费者消费了{data}')
cu = Consumer(q)
pr = Producer(q)
pr.start()
time.sleep(2)
cu.start()