day34

多进程

守护进程(daemon)

'''
进程是一个正在运行的程序
守护进程也是一个普通进程,意思是一个进程可以守护另一个进程
守护进程会随着被守护进程的结束而结束
'''
import multiproecssing
import time

def task():
print('进程开始')
time.sleep(50)
print('进程结束')
if __name__ == '__main__':
print('准备创建进程')
p = multiprocessing.Process(target = task)
p.deamon = True
p.start()
time.sleep(3)
print('进程结束')

互斥锁

'''
并发带来的资源的竞争问题,当多个进程同时要操作同一个资源时,将会导致数据错乱
如果资源已经被锁了,那么别的进程就无法使用
互斥锁并不是把文件或者说资源锁起来,只是在代码层面限制了代码的执行
'''
from multiproecssing import Process,Lock
import time,random

def task1(lock)
lock.acquire()
print('hello world')
   print('i am lilei')
   print('i am boy')
   lock.release()
def task2()
lock.acquire()
print('hello world')
   print('i am lilei')
   print('i am boy')
   lock.release()
def task3()
lock.arquire()
print('hello world')
   print('i am lilei')
   print('i am boy')
   lock.release()

if __name__ == '__main__':
   p1 = Process(target = task1,args = (lock,))
   p2 = Process(target = task2,args = (lock,))
   p3 = Process(target = task3,args = (lock,))

# 注:想要保证数据安全,必须保证所有进程使用的是同一把锁,并且一次acquire要对应一次release
# jion也能实现顺序访问,但是jion是强行把并发变成了串行,并且会造成父进程等待子进程执行完毕
# 粒度:使用互斥锁可以锁任意数量的代码,锁住的代码越多,粒度越大,效率越低,安全性越高
# Mysql中不同的隔离级别,就是不同的粒度

IPC(进程间通讯)

'''
进程之间内存是相互隔离的,当一个进程想要把数据给另外一个进程,就需要考虑IPC
管道(subprosecc):只能单项通讯
文件:在硬盘上创建共享文件,速度慢
socket:编程复杂度较高
共享内存:由操作系统来分配,速度快,数据量不能太大
'''
from multiprocessing import Process Manager,Lock
import time

def task(data,l):
   l.acquire()
   num = data['num']
   time.sleep(0,1)
   data['num'] = num-1
   l.release()


if __name__ == '__main__':
   m = Manager()
   data = m.dict({'num':10})
   l = lock()
   for i in range(10):
       p = Process(target=task,args=(data,l))
       p.start()
   time.sleep(2)
   print(data)

Queue队列

'''
队列是一种特殊的数据结构,先存储的先取出
相反的是堆栈,先存储的后取出
函数嵌套调用时,执行顺序时先进后出,称为函数栈
调用函数时,函数入栈,函数结束就出栈
'''
from multiprocessing import Queue
# 创建队列 不指定maxsize 则没有数量限制
q = Queue(3)
# 存储元素
# q.put("abc")
# q.put("hhh")
# q.put("kkk")

# print(q.get())
# q.put("ooo")   # 如果容量已经满了,在调用put时将进入阻塞状态 直到有人从队列中拿走数据有空位置 才会继续执行

#取出元素
# print(q.get())# 如果队列已经空了,在调用get时将进入阻塞状态 直到有人从存储了新的数据到队列中 才会继续

# print(q.get())
# print(q.get())


#block 表示是否阻塞 默认是阻塞的   # 当设置为False 并且队列为空时 抛出异常
q.get(block=True,timeout=2)
# block 表示是否阻塞 默认是阻塞的   # 当设置为False 并且队列满了时 抛出异常
# q.put("123",block=False,)
# timeout 表示阻塞的超时时间 ,超过时间还是没有值或还是没位置则抛出异常 仅在block为True有效

生产者消费者模型

"""
解决某种问题的一贯方法
生产者:产生数据的一方
消费者:处理数据的一方
"""
import time,random
from mlutporcessing import Process,Queue
import socket
def eat(q):
   for i in range(10):
       # 要消费
       rose = q.get()
       time.sleep(random.randint(0, 2))
       print(rose,"吃完了!")

# 生产任务
def make_rose(q):
   for i in range(10):
       # 再生产
       time.sleep(random.randint(0, 2))
       print("第%s盘青椒肉丝制作完成!" % i)
       rose = "第%s盘青椒肉丝" % i
       # 将生成完成的数据放入队列中
       q.put(rose)

if __name__ == '__main__':
   # 创建一个共享队列
   q = Queue()
   make_p = Process(target=make_rose,args=(q,))
   eat_p =  Process(target=eat,args=(q,))


   make_p.start()
   eat_p.start()
原文地址:https://www.cnblogs.com/zhuqihui/p/10970170.html