day35

                         守护进程

 

如果b是a的守护进程,a是被守护的进程,a要是挂了,b也就随之结束了

使用场景:

父进程交给了子进程一个任务,任务还没有完成父进程就结束了,子进程就没有继续执行的意义了

eg:

from multiprocessing import Process
import time
 
# 妃子的一生
def task():
    print("入宫了.....")
    time.sleep(50)
    print("妃子病逝了......")
 
if __name__ == '__main__':
    # 康熙登基了
    print("登基了.....")
 
    # 找了一个妃子
    p = Process(target=task)
 
    # 设置为守护进程 必须在开启前就设置好
    p.daemon = True
    p.start()
 
    # 康熙驾崩了
    time.sleep(3)
    print("故事结束了!")
 

                  互斥锁

锁 并不是真的把资源锁起来了,只是在代码层面限制你的代码不能执行。

如果这个资源被锁了,其它进程就无法使用了。

为什么需要:

1.并发将带来资源的竞争问题 

2.当多个进程同时要操作同一个资源时,将会导致数据错乱的问题

解决方案:

1.加join

 ​ 弊端 1.把原本并发的任务变成了穿行,避免了数据错乱问题,但是效率降低了,这样就没必要开子进程了

       2.原本多个进程之间是公平竞争,join执行的顺序就定死了,这是不合理的

2.就是给公共资源加锁,互斥锁

  并不是真正把资源锁带来

 

锁和join的区别:

1.主要:join是把进程的任务全部串行;锁可以锁任意代码 一行也可以 可以自己调整粒度

2.join是固定了执行顺序,会造成父进程等待子进程;锁依然是公平竞争谁先抢到谁先执行,父进程可以做其他事情

 

注:1.不要对同一个程序执行多次acquire,否则会锁死导致其无法执行。一次acquire只能对应一次release

2.想要保住数据安全,必须保证所有进程用同一把锁

 

                抢票编程

过程:
1.查询余票
2.购买
   1.再次查询余票
   2.有余票则购买成功 没有则失败

import json,os,time,random
from multiprocessing import Process,Lock
#查票
def show_ticket():

with open("ticket.json","rt",encoding="utf-8") as f:
  data = json.load(f)
# 模拟延迟

  time.sleep(random.randint(0, 2))
  print(" %s正在查询 剩余票数:%s" % (os.getpid(),data["count"]))

def buy_ticket():
  with open("ticket.json", "rt", encoding="utf-8") as f:
    data = json.load(f)
    if data["count"] > 0:
      data["count"] -= 1
# 模拟延迟
      time.sleep(random.randint(0, 2))
      with open("ticket.json","wt",encoding="utf-8") as f:
        json.dump(data,f)
        print("%s 恭喜你抢票成功!" % os.getpid())
    else:
      print("%s抢票失败! 被人抢走了! 开个加速包试试!" % os.getpid())


def task(lock):
  show_ticket()

  lock.acquire()
  buy_ticket()
  lock.release()


if __name__ == '__main__':

  lock = Lock()

  # 十个人抢票
  for i in range(10):
    p = Process(target=task,args=(lock,))      #实例化

    p.start()

 

                    IPC(进程间通讯)

进程之间内存是相互隔离的,当一个进程想要把数据给另外一个进程,就需考虑IPC.

方式:

管道: 只能单向通讯,数据都是二进制

文件: 在硬盘上创建共享文件

  缺点:速度慢

  优点:数据量几乎没有限制

socket:

编程复杂度较高

共享内存:必须由操作系统来分配 

  优点: 速度快

  缺点: 数据量不能太大

 

              共享内存的方式

1.manager类

不带锁,提供了很多数据结构,list,dic等

所创建出来数据结构具备进程间共享的特点。

2.Queue队列

处理了锁的问题

队列是一种特殊的数据结构,先存储的先取出 就像排队 先进先出

相反的是堆栈,先存储的后取出, 就像衣柜 桶装薯片 先进后出

eg.

from multiprocessing import Queue
# 创建队列 不指定maxsize 则没有数量限制
q = Queue(3)
# 存储元素
q.put("abc")
q.put("hhh")
q.put("kkk")


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

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


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

 

              生产者消费者模型

 

产生数据的一方称之为生产者,处理数据的一方称之为消费者。

问题:

二者处理速度不平衡,快的要等待慢的

怎么解决:

将双方分开,一方专门生产,一方专门处理。这样数据就不能直接交互,双方需要共同的容器。

eg.

import time,random

from multiprocessing import Process,Queue

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()

 

 

 

 

posted @ 2019-06-03 19:22  呼吸决定丶  阅读(82)  评论(0)    收藏  举报