day34——僵尸进程和孤儿进程、互斥锁、进程之间的通信
day34
僵尸进程和孤儿进程
基于unix环境(linux,macOS)
主进程需要等待子进程结束之后,主进程才结束
主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收
为什么主进程不在子进程结束后马上对其回收呢?
- 主进程与子进程是异步关系,主进程无法马上捕获进程什么时候结束
- 如果子进程结束之后马上在内存中释放资源,主进程就没有办法监测子进程的状态了
unix针对于上面的问题,提供了一个机制
所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容,(进程号,结束时间,运行状态),等待主进程监测回收
僵尸进程:所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态
僵尸进程有无危害?
如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号
孤儿进程
- 父进程由于某种原因结束了,但是子进程还在运行中,这些子进程就成了孤儿进程。
- 父进程如果结束了,所有的孤儿进程就会被init进程回收,init就会变成父进程,对其进行回收
僵尸进程如何解决?
父进程产生了大量进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程,由init进程回收
互斥锁
定义:互斥锁就是在保证子进程串行的同时,也保证了子进程执行顺序的随机性,以及数据的安全性
lock与join的区别
共同点:都可以把并发变成串行,保证了顺序
不同点:join人为设定顺序,lock让其争抢顺序,保证了公平性
三个同事 同时用一个打印机打印内容
三个进程模拟三个同事,输出平台模拟打印机
# 版本一
from multiprocessing import Process
import time
import random
import os
def task1():
print(f"{os.getpid()}开始打印了")
time.sleep(random.randint(1,3))
print(f"{os.getpid()}打印结束了")
def task2():
print(f"{os.getpid()}开始打印了")
time.sleep(random.randint(1,3))
print(f"{os.getpid()}打印结束了")
def task3():
print(f"{os.getpid()}开始打印了")
time.sleep(random.randint(1,3))
print(f"{os.getpid()}打印结束了")
if __name__ == '__main__':
p1 = Process(target=task1)
p2 = Process(target=task2)
p3 = Process(target=task3)
p1.start()
p2.start()
p3.start()
# 现在是所有的进程都并发的抢占打印机
# 并发是以效率优先的,但是目前我们的需求:顺序优先
# 多个进程共抢一个资源时,要保证顺序优先:串行,一个一个来
# 版本二
from multiprocessing import Process
import time
import random
import os
def task1(p):
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
def task2(p):
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
def task3(p):
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
if __name__ == '__main__':
p1 = Process(target=task1, args=("p1",))
p2 = Process(target=task2, args=("p2",))
p3 = Process(target=task3, args=("p3",))
p1.start()
p1.join()
p1.start()
p1.join()
p1.start()
p1.join()
# 我们利用join解决串行的问题,保证了顺序优先,但是这个谁先谁后时固定的
# 这样不合理,你在争抢同一个资源的时候,应该时先到先得,保证公平
# 版本三
from multiprocessing import Process
from multiprocessing import Lock
import time
import random
import os
def task1(p, lock):
# lock.acquire() 不可重复使用,会导致阻塞
lock.acquire()
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
lock.release()
def task2(p, lock):
lock.acquire()
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
lock.release()
def task3(p, lock):
lock.acquire()
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
lock.release()
def task4(p, lock):
lock.acquire()
print(f"{p}开始打印了")
time.sleep(random.randint(1,3))
print(f"{p}打印结束了")
lock.release()
if __name__ == '__main__':
mutex = Lock()
p1 = Process(target=task1, args=("p1", mutex))
p2 = Process(target=task2, args=("p2", mutex))
p3 = Process(target=task3, args=("p3", mutex))
p4 = Process(target=task4, args=("p4", mutex))
p1.start()
p2.start()
p3.start()
p4.start()
进程之间的通信
基于文件通信
进程在内存级别是隔离的,但是文件在磁盘上不是
利用抢票系统讲解
缺点:
- 效率低
- 自己加锁麻烦而且很容易出现死锁
抢票系统
1、先可以查票,查询余票数,并发
2、进行购买,向服务端发送请求,服务端接收请求,在后端将票数-1,返回到前端,串行
from multiprocessing import Process
from multiprocessing import Lock
import random
import json
import os
import time
def search():
time.sleep(random.randint(1,3))
with open("ticket.json", encoding="utf-8")as f1:
dic = json.load(f1)
print(f"{os.getpid()}查看了票数,剩余{dic['count']}")
def paid(lock):
with open("ticket.json", encoding="utf-8")as f:
dic = json.load(f)
if dic["count"] > 0:
dic["count"] -= 1
time.sleep(random.randint(1,3))
with open("ticket.json", encoding="utf-8", mode="w")as f1:
json.dump(dic,f1)
print(f"{os.getpid()}购买成功")
def task(lock):
search()
paid()
if __name__ == '__main__':
for i in range(5):
p = Process(target=task)
p.start()
当多个进程共抢一个数据时,如果要保证数据的安全,必须要串行
要想让购买环节进行串行,我们必须要加锁处理
from multiprocessing import Process
from multiprocessing import Lock
import random
import json
import os
import time
def search():
time.sleep(random.randint(1,3))
with open("ticket.json", encoding="utf-8")as f1:
dic = json.load(f1)
print(f"{os.getpid()}查看了票数,剩余{dic['count']}")
def paid(lock):
# lock.acquire()
with open("ticket.json", encoding="utf-8")as f:
dic = json.load(f)
if dic["count"] > 0:
dic["count"] -= 1
time.sleep(random.randint(1,3))
with open("ticket.json", encoding="utf-8", mode="w")as f1:
json.dump(dic,f1)
print(f"{os.getpid()}购买成功")
# lock.release()
def task(lock):
search()
lock.acquire()
paid(lock)
lock.release()
if __name__ == '__main__':
mutex = Lock()
for i in range(15):
p = Process(target=task, args=(mutex,))
p.start()
当很多进程共抢一个资源(数据)时,你要保证顺序(数据的安全),一定要串行
互斥锁:可以公平性的保证顺序以及数据的安全
基于队列通信
队列:把队列理解成一个容器,这个容器可以承载一些数据
队列的特性:先进先出永远保持这个数据。——FIFO
- 介绍
from multiprocessing import Queue
q = Queue()
def func():
print("in func")
q.put(1)
q.put("alex")
q.put([1, 2, 3])
q.put(func)
print(q.get())
print(q.get())
print(q.get())
q.get()()
- 特性
from multiprocessing import Queue
q = Queue(4) # 可以设置队列最大长度(maxsize)
def func():
print("in func")
q.put(1)
q.put("alex")
q.put([1, 2, 3])
q.put(func)
q.put(555,block=False) # 当队列满了时,在进程put数据就会阻塞,如果block=False就会报错而不是阻塞
print(q.get())
print(q.get())
print(q.get(timeout = 3)) # 阻塞3秒,3秒之后还阻塞直接报错
q.get()()
print(q.get(block=False)) # 当数据取完时,在进程get数据也会出现阻塞,直到某个进程put数据。如果block=False就会报错而不是阻塞
基于管道通信
day34——僵尸进程和孤儿进程、互斥锁、进程之间的通信的更多相关文章
- Python并发编程03 /僵孤进程,孤儿进程、进程互斥锁,进程队列、进程之间的通信
Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 目录 Python并发编程03 /僵孤进程,孤儿进程.进程互斥锁,进程队列.进程之间的通信 1. 僵尸进程/孤儿进 ...
- day34 python学习 守护进程,线程,互斥锁,信号量,生产者消费者模型,
六 守护线程 无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁 需要强调的是:运行完毕并非终止运行 #1.对主进程来说,运行完毕指的是主进程代码运行完毕 #2.对主线程来说,运行完 ...
- Python11/12--GIL/互斥锁/进程池
GIL1.全局解释器锁? 锁就是线程里面那个锁 锁是为了避免资源竞争造成数据的错乱 2.python程序的执行过程? 1.启动解释器进程 python.exe 2.解析你的py文件并执行它 每个py程 ...
- 并发编程(二)--利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道
一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似. 2.mu ...
- 并发编程(二)——利用Process类开启进程、僵尸进程、孤儿进程、守护进程、互斥锁、队列与管道
Process类与开启进程.守护进程.互斥锁 一.multiprocessing模块 1.multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模 ...
- python并发编程之多进程1--(互斥锁与进程间的通信)
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python并发编程之多进程1互斥锁与进程间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- Python之网路编程之-互斥锁与进程间的通信(IPC)及生产者消费者模型
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python网络编程中互斥锁与进程之间的通信
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- 4 并发编程-(进程)-守护进程&互斥锁
一.守护进程 主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比崇祯皇帝身边的老太监,崇祯皇帝已死老太监就跟着殉葬了. 关于守护进程需要强调两点: 其一:守护进程会在主进程代码执行结束 ...
随机推荐
- CI持续集成 -- git 与 gitlab
版本控制系统概述 git Git基本概述 Git是一个免费的开源分布式版本控制系统,旨在快速高效地处理从小型到大型项目的所有内容. Git安装配置 #安装Git yum install -y git ...
- WinDbg常用命令系列---!heap
!heap 简介 !heap扩展显示堆使用信息.控制堆管理器中的断点.检测泄漏的堆块.搜索堆块或显示页堆信息.此扩展支持段堆和NT堆.使用!heap没有参数列出所有堆及其类型的堆. 使用形式 !hea ...
- hibernate实现增删改查
1.需要先创建学生实体: package pers.zhb.domain; public class Student { private int studentno; private String s ...
- Python 08 skimage
原文:https://www.cnblogs.com/xdjun/p/7874794.html 命令: pip install numpy pip install scipy pip install ...
- 第03组 Alpha冲刺(1/4)
队名:不等式方程组 组长博客 作业博客 团队项目进度 组员一:张逸杰(组长) 过去两天完成的任务: 文字/口头描述: 制定了初步的项目计划,并开始学习一些推荐.搜索类算法 GitHub签入纪录: 暂无 ...
- 初试angularjs动画(animate)
angularjs不同版本的代码写法各有千秋,动画模块的写法也各有不同,以下是收集到的两大版本的写法,各位请: angularjs1.1.5版本(1.2之前) index.html代码: <!D ...
- Go-Json操作
/** * @Author: jadeshu * @Description: * @File: main * @Version: 1.0.0 * @Date: 2019/11/7 2:33 */ pa ...
- ES6 数组方法 forEach map filter find every some reduce
1. forEach const colors = ['red', 'blue', 'green'] colors.forEach(function (params) { console.log(pa ...
- mysql union 组合查询
mysql> select * from test -> ; +----+------------+-------+-----------+ | id | name | score | s ...
- TreeMap用法总结
TreeMap用法总结 public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap&l ...