Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信

目录

  • Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信

    • 1.昨日回顾
    • 2.僵尸进程和孤儿进程
      • 2.1僵尸进程
      • 2.2孤儿进程
      • 2.3僵尸进程如何解决?
    • 3.互斥锁,锁
      • 3.1互斥锁的应用
      • 3.2Lock与join的区别
    • 4.进程之间的通信
      • 进程在内存级别是隔离的
      • 4.1基于文件通信 (抢票系统)
      • 4.2基于队列通信

Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信

1.昨日回顾

1.创建进程的两种方式: 函数, 类.
2.pid: os.getpid()  os.getppid()
  tasklist
  tasklist| findstr  进程名
3.进程与进程之间是有物理隔离: 不能共享内存的数据.(lock,队列)
4.join阻塞:  让主进程等待子进程结束之后,在执行.
5.其他属性: terminate() is_alive() name,
6.守护进程: 将子进程设置成守护进程,当主进程结束了,子进程就马上结束.

2.僵尸进程和孤儿进程

2.1僵尸进程

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程.
#基于unix环境(linux,macOS)
    #主进程需要等待子进程结束之后,主进程才结束
主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收.

#为什么主进程不在子进程结束后马上对其回收呢?
# 1. 主进程与子进程是异步关系.主进程无法马上捕获子进程什么时候结束.
# 2. 如果子进程结束之后马上再内存中释放资源,主进程就没有办法监测子进程的状态了.
#unix针对于上面的问题,提供了一个机制.
#所有的子进程结束之后,立马会释放掉文件的操作链接,内存的大部分数据,但是会保留一些内容: 进程号,结束时间,运行状态,等待主进程监测,回收.
僵尸进程: 所有的子进程结束之后,在被主进程回收之前,都会进入僵尸进程状态.
#僵尸进程有无危害???
#如果父进程不对僵尸进程进行回收(wait/waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号.

2.2孤儿进程

#父进程由于某种原因结束了,但是你的子进程还在运行中,这样你的这些子进程就成了孤儿进程.你的父进程如果结束了,你的所有的孤儿进程就会被init进程的回收,init就变成了你的父进程,对你进行回收.

2.3僵尸进程如何解决?

#父进程产生了大量子进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程,将所有的僵尸进程变成孤儿进程进程,由init进行回收.

3.互斥锁,锁

3.1互斥锁的应用

# 三个同事 同时用一个打印机打印内容.
# 三个进程模拟三个同事, 输出平台模拟打印机.

# 版本一:
# 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',))
#
#     p2.start()
#     p2.join()
#     p1.start()
#     p1.join()
#     p3.start()
#     p3.join()

# 我们利用join 解决串行的问题,保证了顺序优先,但是这个谁先谁后是固定的.
# 这样不合理. 你在争抢同一个资源的时候,应该是先到先得,保证公平.

# 版本3:

from multiprocessing import Process
from multiprocessing import Lock
import time
import random
import os

def task1(p,lock):
    '''
    一把锁不能连续锁两次
    lock.acquire()
    lock.acquire()
    lock.release()
    lock.release()
    '''
    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()

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

    p2.start()
    p1.start()
    p3.start()

3.2Lock与join的区别

#共同点: 都可以把并发变成串行, 保证了顺序.
#不同点: join人为设定顺序,lock让其争抢顺序,保证了公平性.

4.进程之间的通信

进程在内存级别是隔离的

4.1基于文件通信 (抢票系统)

# 抢票系统.
# 1. 先可以查票.查询余票数.  并发
# 2. 进行购买,向服务端发送请求,服务端接收请求,在后端将票数-1,返回到前端. 串行.

# from multiprocessing import Process
# import json
# import time
# import os
# import random
#
#
# 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():
#     with open('ticket.json', encoding='utf-8') as f1:
#         dic = json.load(f1)
#     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():
#     search()
#     paid()
#
#
# if __name__ == '__main__':
#
#     for i in range(6):
#         p = Process(target=task)
#         p.start()

# 当多个进程共强一个数据时,如果要保证数据的安全,必须要串行.
# 要想让购买环节进行串行,我们必须要加锁处理.

#
# from multiprocessing import Process
# from multiprocessing import Lock
# import json
# import time
# import os
# import random
#
#
# 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():
#     with open('ticket.json', encoding='utf-8') as f1:
#
#         dic = json.load(f1)
#     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()
#     lock.acquire()
#     paid()
#     lock.release()
#
# if __name__ == '__main__':
#     mutex = Lock()
#     for i in range(6):
#         p = Process(target=task,args=(mutex,))
#         p.start()

# 当很多进程抢一个资源(数据)时, 你要保证顺序(数据的安全),一定要串行.
# 互斥锁: 可以公平性的保证顺序以及数据的安全.

# 基于文件的进程之间的通信:
    # 效率低.
    # 自己加锁麻烦而且很容易出现死锁.

4.2基于队列通信

队列: 把队列理解成一个容器,这个容器可以承载一些数据,
队列的特性: 先进先出永远保持这个数据. FIFO(first in first out).
# 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())
# f = q.get()
# f()

# from multiprocessing import Queue
# q = Queue(3)
#
# q.put(1)
# q.put('alex')
# q.put([1,2,3])
# # q.put(5555)  # 当队列满了时,在进程put数据就会阻塞.
# # q.get()
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())  # 当数据取完时,在进程get数据也会出现阻塞,直到某一个进程put数据.

# from multiprocessing import Queue
# q = Queue(3)  # maxsize
#
# q.put(1)
# q.put('alex')
# q.put([1,2,3])
# q.put(5555,block=False)
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get(timeout=3))  # 阻塞3秒,3秒之后还阻塞直接报错.
# print(q.get(block=False))

# block=False 只要遇到阻塞就会报错.

原文地址:https://www.cnblogs.com/liubing8/p/11391721.html

时间: 2024-08-05 08:28:04

Python并发编程03/僵尸孤儿进程,互斥锁,进程之间的通信的相关文章

python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终端 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

python 并发编程 多线程 死锁现象与递归锁

一 死锁现象 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁 from threading import Thread from threading import Lock import time # 实例化两把不同的锁 mutexA = Lock() mutexB = Lock() class MyThread(Threa

11.python并发入门(part3 多线程与互斥锁)

一.锁的概念. 锁,通常被用来实现共享数据的访问,为每一个共享的数据,创建一个Lock对象(一把锁),当需要访问这个共享的资源时,可以调用acquire方法来获取一个锁的对象,当共享资源访问结束后,在调用release方法去解锁. 二.python中的互斥锁. 在介绍互斥锁之前,先来一起看一个例子.(每个线程对num实现一次-1的操作) import threading import  time num = 200  #每个线程都共享这个变量. tread_list = [] def count

python并发编程之多进程

python并发编程之多进程 一.什么是进程 进程:正在进行的一个过程或者一个任务,执行任务的是CPU. 原理:单核加多道技术 二.进程与程序的区别 进程是指程序的运行过程 需要强调的是:同一个程序执行两次是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播放苍井空,另一个可以播放武藤兰. 三.并发与并行 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务. (1)并发

Python并发编程之进程2

引言 本篇介绍Python并发编程下的进程,先介绍进程的相关知识,然后对python中multiprocessing模块进行介绍(Process.Pipe.Queue以及 Lock). 进程(process) 在面向线程设计的系统(如当代多数操作系统.Linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器. 进程拥有自己独立的内存空间,所属线程可以访问进程的空间. 程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 例如,我们在PyCharm开发环境中写

开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型

开启子进程的两种方式 # # # 方式一: # from multiprocessing import Process # import time # # def task(x): # print('%s is running' %x) # time.sleep(3) # print('%s is done' %x) # # if __name__ == '__main__': # # Process(target=task,kwargs={'x':'子进程'}) # p=Process(tar

Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池

目录 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 2.死锁现象与递归锁 2.1死锁现象 2.2递归锁 3.信号量 4.GIL全局解释器锁 4.1背景 4.2为什么加锁 5.GIL与Lock锁的区别 6.验证计算密集型IO密集型的效率 6.1 IO密集型 6.2 计算密集型 7.多线程实现socket通信 7.1服务端 7.2客户端 8.进程池,线程池 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 #生产者消

python并发编程之多进程1------互斥锁与进程间的通信

一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全. 1.上厕所的小例子:你上厕所的时候肯定得锁门吧,有人来了看见门锁着,就会在外面等着,等你吧门开开出来的时候,下一个人才去上厕所. 1 from multiprocessing import Process,Lock 2 import os 3

进程,操作系统,Python并发编程之多进程

1.进程基础知识 1.程序:若干文件 2.进程:一个正在执行的文件,程序 3.进程被谁执行:cpu最终运行指定的程序 4.操作系统调度作用:将磁盘上的程序加载到内存,然后交由CPU去处理,一个CPU正在运行的一个程序,就叫开启了一个进程 2.操作系统 1.操作系统:存在于硬盘与软件之间,管理.协调.控制软件与硬件的交互 2.操作系统的作用:将一些复杂的硬件封装成简单的借口,便于使用;合理地调度分配多个进程与cpu的关系,让其有序化 3.操作系统发展史 ①第一代电子计算机(1940-1955) 二