小知识点:在子进程中不能使用input输入!

一.守护进程

守护进程表示一个进程b 守护另一个进程a 当被守护的进程结束后,那么守护进程b也跟着结束了

应用场景:之所以开子进程,是为了帮助主进程完成某个任务,然而,如果主进程认为自己的事情一旦做完了就没有必要使用子进程了,就可以将子进程设置为守护进程

例如:在运行qq的过程,开启一个进程,用于下载文件,然而文件还没有下载完毕,qq就退出了,下载任务也应该跟随qq的退出而结束.

from multiprocessing import Process
import time
def task():
  print('妃子的一生')
  time.sleep(3)
  print('妃子88了')
if __name__ == '__main__':
  fz = Process(target=task)
  fz.daemon = True # bool类型 将子进程作为主进程的守护进程,注意:必须在开启子进程前设置!
  fz.start()
  print('皇帝登基!')
  print('当了三年皇帝!')
  time.sleep(1)
  print('皇帝驾崩了!')

二.互斥锁

当多个进程共享一个数据时,可能会造成数据错乱

1.使用join来让这些进程串行,但是这样就造成了无法并发,并且进程执行的顺序就固定了

2.使用锁 将需要共享的数据增加锁 其他的进程在访问数据时,就必须等待当前进程使用完毕

不使用锁:
多个任务在共享一个数据时
串行效率低 但是不会出问题
并发效率高 但是数据可能错乱
使用锁:
from multiprocessing import Process,Lock
import time,random
def task1(lock):
  lock.acquire() #是一个阻塞函数,会等到别的子进程释放锁才能继续执行
  print('name1:henry')
  time.sleep(random.randint(1,2))
  print('age1:29')
  time.sleep(random.randint(1, 2))
  print('sex1:man')
  lock.release()
def task2(lock):
  lock.acquire()
  print('name2:wendy')
  time.sleep(random.randint(1, 2))
  print('age2:24')
  time.sleep(random.randint(1, 2))
  print('sex2:woman')
  lock.release()
def task3(lock):
  lock.acquire()
  print('name3:irene')
  time.sleep(random.randint(1, 2))
  print('age3:27')
  time.sleep(random.randint(1, 2))
  print('sex3:woman')
  lock.release()
if __name__ == '__main__':
  lock = Lock()
  p1 = Process(target=task1,args=(lock,))
  p1.start()
  p2 = Process(target=task2,args=(lock,))
  p2.start()
  p3 = Process(target=task3,args=(lock,))
  p3.start()

join 和 锁的区别

1.join中顺序是固定的,不公平

2.join是完全的串行,而锁可以使部分代码串行 其他代码还是并发

互斥锁的使用场景_抢票
from multiprocessing import Process,Lock
import json,time,random
def check_ticket(user):
  time.sleep(random.randint(1,3))
  with open('ticket.json',mode='rt',encoding='utf-8') as f:
    dic = json.load(f)
    print('用户%s,您好!还剩%s张票!'%(user,dic['count']))
def buy_ticket(user):
  with open('ticket.json',mode='rt',encoding='utf-8') as f:
    dic = json.load(f)
    if dic['count'] > 0:
      time.sleep(random.randint(1,3))
      dic['count'] -= 1
      with open('ticket.json',mode='wt',encoding='utf-8') as f2:
        json.dump(dic,f2)
        print('用户%s购票成功!'%user)
def task(user,lock):
  check_ticket(user)
  lock.acquire()
  buy_ticket(user)
  lock.release()

if __name__ == '__main__':
  lock = Lock()
  for i in range(1,11):
    p = Process(target=task,args=(i,lock))
    p.start()

锁的本质是一个bool类型的数据,在执行代码前会先判断这个值

注意 在使用锁的时候必须保证是同一个锁

锁的实现原理 伪代码
l = False
def task(lock):
  global l
  if l == False:
    l = True
    print('你好!')
  l = False

Lock和Rlock的区别:

from multiprocessing import Lock
lock = Lock()
lock.acquire()
lock.acquire()
print('我出来了!')
lock.release()
#这个程序会卡死

from multiprocessing import RLock
lock = RLock()
lock.acquire()
lock.acquire()
print('我出来了!')
lock.release()
#这个程序会打印出结果

Rlock表示可重复锁,特点是可以多次执行acquire
Rlock在执行多次acquire时和普通Lock没有任何区别
而Lock如果多次执行acquire就会被锁死
还要注意的一点是Rlock在一个子进程中执行了几次acquire就要执行几次release,这样才会执行下一个子进程

from multiprocessing import Process,RLock
import time
def task(i,lock):
  lock.acquire()
  lock.acquire()
  print(i)
  time.sleep(3)
  lock.release()
  lock.release()
if __name__ == '__main__':
  lock = RLock()
  p1 = Process(target=task,args=(1,lock))
  p1.start()
  p2 = Process(target=task,args=(2,lock))
  p2.start()

死锁:

指的是锁无法打开导致程序卡死 首先要明确的是一把锁是无法锁死的,正常开发时一把锁足够使用,不需要开多把锁

from multiprocessing import Process,Lock
import time
def task1(l1,l2,i):
  l1.acquire()
  print('%s抢走了碗!'%i)
  time.sleep(1)
  l2.acquire()
  print('%s抢走了筷子!'%i)
  print('%s开始吃饭!'%i)
  l1.release()
  l2.release()
def task2(l1,l2,i):
l2.acquire()
  print('%s抢走了筷子!'%i)
  l1.acquire()
  print('%s抢走了碗!'%i)
  print('%s开始吃饭!'%i)
  l2.release()
  l1.releaase()
if __name__ == '__main__':
  l1 = Lock()
  l2 = Lock()
  p1 = Process(target=task1,args=(l1,l2,'henry'))
  p1.start()
  p2 = Process(target=task2,args=(l1,l2,'seulgi'))
  p2.start()

三.IPC

由于进程之间是相互独立的,所以需要设立方案使得各个进程之间可以相互传递数据

1.使用共享文件,多个进程同时读写一个文件

IO速度慢,传输数据大小不受限制

2.管道 是基于内存的,速度快,但是是单向的,用起来麻烦

3.申请共享内存空间,多个进程可以共享这个内存区域(重点)

速度快,但数据量不能太大

from multiprocessing import Manager,Process
def work(d):
  d['count'] -= 1
if __name__ == '__main__':
  with Manager() as m:
    dic = m.dict({'count':100}) #创建一个共享的字典
    p_l = []
    for i in range(100):
    p = Process(target=work,args=(dic,))
    p_l.append(p)
    p.start()

  for P in p_l:
    p.join()
  print(dic)

四.队列

队列不只用于进程间通讯,也是一种常见的数据容器

特点:先进先出

优点:即使在多进程下,也可以保证数据不会错乱,因为put和get默认都是阻塞的

堆栈:先进后出

from multiprocessing import Queue
q = Queue(1)#创建一个对列,最多可以存一个数据
q.put('henry')
q.put('wendy') #当容器中已经填满的时候,put默认会阻塞
print('over')

from multiprocessing import Queue
q = Queue(1)#创建一个对列,最多可以存一个数据
q.put('henry')
print(q.get())
print(q.get())#当容器中已经没有数据时,get默认会阻塞
print('over')

from multiprocessing import Queue
q = Queue(1)#创建一个对列,最多可以存一个数据
q.put('henry')
q.put('wendy',False) #第二个参数设置为False表示不会阻塞,无论容器满了没满都会强行往里面塞,如果满了抛出异常

from multiprocessing import Queue
q = Queue(1)#创建一个对列,最多可以存一个数据
q.put('henry')
print(q.get())
print(q.get(timeout=3))#timeout 仅用于阻塞时

五.生产者与消费者模型

什么是生产者消费者模型?

生产者产生数据的一方

消费者处理数据的一方

例如需要做一个爬虫?

1.爬取数据

2.解析数据

爬取和解析都是耗时的操作,如果正常按照顺序来编写代码,会造成解析需要等待爬取,爬取也需要等待解析,这样的话效率就会很低

要提高效率,就是让生产者和消费者解开耦合,自己干自己的

如何实现:

1.将两个任务分配给不同的进程

2.提供一个进程共享的数据容器

from multiprocessing import Process,Queue
import time,random
# 爬数据
def get_data(q):
  for num in range(1,6):
    print('正在爬取第%s个数据...'%num)
    time.sleep(random.randint(1,2))
    print('第%s个数据爬取完成!'%num)
    #把数据装到队列中
    q.put('第%s个数据'%num)
#解析数据
def parse_data(q):
  for num in range(1,6):
    #取出数据
    data = q.get()
    print('正在解析%s...'%data)
    time.sleep(random.randint(1,2))
    print('%s解析完成!'%data)
if __name__ == '__main__':
  #共享数据容器
  q = Queue()
  #生产者进程
  produce = Process(target=get_data,args=(q,))
  produce.start()
  #消费者进程
  customer = Process(target=parse_data,args=(q,))
  customer.start()

守护进程,互斥锁,IPC,队列,生产者与消费者模型的更多相关文章

  1. 进程(守护进程--互斥锁--IPC机制--生产者模型--僵尸进程与孤儿进程--模拟抢票--消息队列)

    目录 一:进程理论知识 1.理论知识 二:什么是进程? 三:僵尸进程与孤儿进程 1.僵尸进程 四:守护进程 1.什么是守护进程? 2.主进程创建守护进程 3.守护进程 五:互斥锁(模拟多人抢票) 1. ...

  2. 守护模式,互斥锁,IPC通讯,生产者消费者模型

    '''1,什么是生产者消费者模型 生产者:比喻的是程序中负责产生数据的任务 消费者:比喻的是程序中负责处理数据的任务 生产者->共享的介质(队列)<-消费者 2,为何用 实现了生产者与消费 ...

  3. 20181229(守护进程,互斥锁,IPC,生产者和消费者模型)

    一.守护进程 守护进程:一个进程B守护另一个进程A,当被守护的进程A结束,进程B也就结束了.(不一定同生,但会同死) 两个特点: ①守护进程会在主进程代码执行结束后就终止 ②守护进程内无法再开启子进程 ...

  4. 守护进程,互斥锁,IPC,生产者与消费者模型

    守护进程: b 进程守护 a进程,当a进程执行完毕时,b进程会跟着立马结束 守护进程用途: 如果父进程结束了,子进程无需运行了,就可以将子进程设置为父进程的守护进程 例如我们qq视频聊天时,当我们退出 ...

  5. 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型

    1  守护进程: 主进程 创建 守护进程   辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...

  6. 4 并发编程-(进程)-守护进程&互斥锁

    一.守护进程 主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比崇祯皇帝身边的老太监,崇祯皇帝已死老太监就跟着殉葬了. 关于守护进程需要强调两点: 其一:守护进程会在主进程代码执行结束 ...

  7. 8.9 day30 并发编程 进程理论 进程方法 守护进程 互斥锁

    多道技术 1.空间上的复用 多个程序共用一套计算机硬件 多道技术原理 2.时间上的复用 ​ 切换+保存状态 ​ 1.当一个程序遇到IO操作 操作系统会剥夺该程序的CPU执行权限( 提高了CPU的利用率 ...

  8. python并发编程-进程理论-进程方法-守护进程-互斥锁-01

    操作系统发展史(主要的几个阶段) 初始系统 1946年第一台计算机诞生,采用手工操作的方式(用穿孔卡片操作) 同一个房间同一时刻只能运行一个程序,效率极低(操作一两个小时,CPU一两秒可能就运算完了) ...

  9. (day29) 进程互斥锁 + 线程

    目录 进程互斥锁 队列和堆栈 进程间通信(IPC) 生产者和消费者模型 线程 什么是线程 为什么使用线程 怎么开启线程 线程对象的属性 线程互斥锁 进程互斥锁 进程间数据不共享,但是共享同一套文件系统 ...

随机推荐

  1. HDU 1757 A Simple Math Problem(矩阵)

    A Simple Math Problem [题目链接]A Simple Math Problem [题目类型]矩阵快速幂 &题解: 这是一个模板题,也算是入门了吧. 推荐一个博客:点这里 跟 ...

  2. LeetCode121.买卖股票的最佳时机

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股票. 示例 ...

  3. 深入解析Java反射(1) - 基础

    深入解析Java反射(1) - 基础 最近正筹备Samsara框架的开发,而其中的IOC部分非常依靠反射,因此趁这个机会来总结一下关于Java反射的一些知识.本篇为基本篇,基于JDK 1.8. 一.回 ...

  4. report源码分析——宏的执行

    uvm_info,uvm_error其实是对uvm_report_info,uvm_report_error的封装. 其中warning,error,fatal,macros默认都是定义为UVM_NO ...

  5. 【CDH学习之一】CDH简介

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 zookeeper-3.4.11 一.CDH在商业应用中,对 ...

  6. java中的神奇"this"

    java中的神奇"this",神奇的原因事它能不用new就可以直接创造一个对象出来,后来研究发现,其实java的“this”使用时,也是"new"了一个当前的对 ...

  7. MQ(转)

    1. 到底什么时候该使用MQ? 1). 典型场景一:数据驱动的任务依赖 采用MQ的优点是: a. 不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行 b. 依赖多个任务,被多个任务依 ...

  8. Linux基础命令---显示域名ypdomainname

    ypdomainname   ypdomainname指令显示由函数“getdomainname”返回的主机域名,使用这个指令也可以设置一个主机NIS/YP域名. 此命令的适用范围:RedHat.RH ...

  9. js如何获取服务器端时间?

    用js做时间校正,获取本机时间,是存在bug的. 使用js也可获取到服务器时间,原理是使用 ajax请求,返回的头部信息就含有服务器端的时间信息,获取到就可以了.以下: 1.依赖jQuery 代码: ...

  10. 使用tableau去将存入mysql都地区点击率进行了展示 感觉很好用

    1.连接数据源很多选项:hive mysql Oracle 等所有数据库 2.写上hive2的那个客户端连接,下边会显示出让我装连接的驱动 ,所有jdbc都需要这样 点进去找到windows的下载一键 ...