day35

##############守护进程

什么是守护进程

​ 进程是一个正在运行的程序

​ 守护进程也是一个普通进程

​ 意思是一个进程可以守护另一个进程

例如

​ 康熙要是一个进程的话,后宫佳丽都是守护者

​ 如果康熙挂了, 后宫佳丽们要陪葬

结论:

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

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("故事结束了!")

 

############如果被守护进程没了的话,守护进程也直接就没了


使用场景:

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

​ 例如:qq 接收到一个视频文件,于是开启了一个子进程来下载,如果中途退出了qq,下载任务就没必须要继续运行了

#######################互斥锁

## 什么是互斥锁

互斥锁 互相排斥的锁,我在这站着你就别过来,(如果这个资源已经被锁了,其他进程就无法使用了)

需要强调的是: 锁 并不是真的把资源锁起来了,只是在代码层面限制你的代码不能执行(#########把一个变量设置为False)

### 为什么需要互斥锁:

并发将带来资源的竞争问题
当多个进程同时要操作同一个资源时,将会导致数据错乱的问题

##########尝试使用john

加join,
​ 弊端 1.把原本并发的任务变成了穿行,避免了数据错乱问题,但是效率降低了,这样就没必要开子进程了
​ 2.原本多个进程之间是公平竞争,join执行的顺序就定死了,这是不合理的

########使用锁的方法

解决方案2:

​ 就是给公共资源加锁,互斥锁
​ 互斥锁 互相排斥的锁,我在这站着你就别过来,(如果这个资源已经被锁了,其他进程就无法使用了),锁 并不是真的把资源锁起来了,只是在代码层面限制你的代码不能执行

#### 锁和join的区别:
​ 1.

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

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

案例

from multiprocessing import Process,Lock
import time,random

def task1(lock):
  # 要开始使用了 上锁
  lock.acquire() #就等同于一个if判断
  print("hello iam jerry")
  time.sleep(random.randint(0, 2))
  print("gender is boy")
  time.sleep(random.randint(0, 2))
  print("age is 15")
#用完了就解锁
  lock.release()

def task2(lock):
  lock.acquire()
  print("hello iam owen")
  time.sleep(random.randint(0,2))
  print("gender is girl")
  time.sleep(random.randint(0,2))
  print("age is 48")
  lock.release()

def task3(lock):
  lock.acquire()
  print("hello iam jason")
  time.sleep(random.randint(0,2))
  print("gender is women")
  time.sleep(random.randint(0,2))
  print("age is 26")
  lock.release()

if __name__ == '__main__':
  lock = Lock()

  p1 = Process(target=task1,args=(lock,))
  p2 = Process(target=task2,args=(lock,))
  p3 = Process(target=task3,args=(lock,))

  p1.start()
  # p1.join()

  p2.start()
  # p2.join()

  p3.start()
  # p3.join()

# 锁的伪代码实现

# if my_lock == False:
  # my_lock = True
  # #被锁住的代码
  my_lock = False 解锁

注意1: 不要对同一把执行多出acquire 会锁死导致程序无法执行 一次acquire必须对应一次release

注意2:想要保住数据安全,必须保住所有进程使用同一把锁

###############IPC,Queue

# IPC

​ 进程间通讯

​ 通讯指的就是交换数据

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

方式:

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

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

​ 缺点:速度慢

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

​ socket:

​ 编程复杂度较高

共享内存:必须由操作系统来分配 要掌握的方式*****

​ 优点: 速度快

​ 缺点: 数据量不能太大

## 共享内存的方式

## 1.Manager类 了解

​ Manager提供很多数据结构 list dict等等

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

需要强调的是 Manager创建的一些数据结构是不带锁的 可能会出现问题

2.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有效
```

 

##############生产消费者模型

## 是什么

​ 模型 就是解决某个问题套路

​ 产生数据的一方称之为生产者

​ 处理数据的一方称之为消费者

​ 例如: 爬虫 生活中到处都是这种模型

​ 饭店 厨师就是生产者 你吃饭的人就是消费者

## 生产者和消费者出啥问题了? 解决什么问题

​ 生产者和消费,处理速度不平衡,一方快一方慢,导致一方需要等待另一方

## 生产者消费者模型解决这个问题的思路: 怎么解决

​ 原本,双方是耦合 在一起,消费必须等待生产者生成完毕在开始处理, 反过来

​ 如果消费消费速度太慢,生产者必须等待其处理完毕才能开始生成下一个数据

### 解决的方案:

​ 将双方分开来.一专门负责生成,一方专门负责处理

​ 这样一来数据就不能直接交互了 双方需要一个共同的容器

​ 生产者完成后放入容器,消费者从容器中取出数据(就是厨师把菜做好了,放在一个地方,消费者啥时候来吃都可以)

​ 这样就解决了双发能力不平衡的问题,做的快的一方可以继续做,不需要等待另一方

 

 

 

把生产者和消费者分开来了

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

########把生产者的东西put到消费者里面.

 

posted @ 2019-06-03 21:24  轩辕12  阅读(107)  评论(0编辑  收藏  举报