~~并发编程(四):进程方法~~

进击のpython


并发编程——进程方法



开启了进程之后,就要学习一下对应的方法

本小节对进程的一些方法进行简单的理解:

1.Process的join方法

2.Process的terminate与is_alive

Process的join方法

p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)

? timeout是可选的超时时间

首先,系统在运行的过程中可能会出现这样的情况:

1.主进程和子进程彼此独立,在都完成运行之后,由系统进行统一回收

2.主进程等子进程运行完毕之后再执行

第一种情况好说,第二种情况就需要有一种机制能够让主进程检测子进程是否运行完毕

在子进程执行完毕后才继续执行,否则一直在原地阻塞,这就是join方法的作用

from multiprocessing import Process

def func(name, *args, **kwargs):
    print(f'{name}执行!')
    pass

if __name__ == '__main__':
    p = Process(target=func, args=('子进程',))
    p.start()
    p.join()
    print('我是主进程...')

在没有利用join方法的时候,执行顺序是这样的

我是主进程...
子进程执行!

利用join之后,执行顺序就变成

子进程执行!
我是主进程...

可以看到,主进程的代码在等待子进程代码运行结束才开始执行

那是变成串行了吗???

import time
from multiprocessing import Process

def func(name, times, *args, **kwargs):
    time.sleep(times)
    print(f'{name}执行!')
    pass

if __name__ == '__main__':
    p1 = Process(target=func, args=('子进程1', 1))
    p2 = Process(target=func, args=('子进程2', 2))
    p3 = Process(target=func, args=('子进程3', 3))

    p1.start()
    p2.start()
    p3.start()
    start_time = time.time()
    p1.join()
    p2.join()
    p3.join()
    print(f'子进程花费时间:{time.time()-start_time}')
    print('我是主进程...')

如果将join理解成串行,那么,子程序的执行时间应该是1+2+3 = 6s多

先执行p1,睡1s,再执行p2,睡2s,再执行p3,睡3s

那我们来看一下执行结果:

子进程1执行!
子进程2执行!
子进程3执行!
子进程花费时间:3.270955801010132
我是主进程...

时间是3s多,说明不是串行,依旧是并发执行

在开始介绍过,join是主进程等待子进程运行结束,再运行

p1 p2 p3 都是子进程,彼此不需要等待,是并发执行的状态

所以紫禁城互相都是共享时间的,都是在执行的

而当子进程中3s的执行完了,也就意味着所有的子进程执行完毕了

才会执行主进程,所以子进程的执行时间只有3s多

上述的代码也可以优化一下:

import time
from multiprocessing import Process

def func(name, times, *args, **kwargs):
    time.sleep(times)
    print(f'{name}执行!')
    pass

if __name__ == '__main__':
    p1 = Process(target=func, args=('子进程1', 1))
    p2 = Process(target=func, args=('子进程2', 2))
    p3 = Process(target=func, args=('子进程3', 3))
    ls = [p1, p2, p3]
    for l in ls:
        l.start()
    start_time = time.time()
    for l in ls:
        l.join()
    print(f'子进程花费时间:{time.time()-start_time}')
    print('我是主进程...')

Process的terminate与is_alive

p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方 法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁

p.is_alive():如果p仍然运行,返回True

import time
from multiprocessing import Process

def func(name, *args, **kwargs):
    print(f'{name}执行!')
    pass

if __name__ == '__main__':
    p = Process(target=func, args=('子程序',))
    p.start()
    p.terminate()
    print(p.is_alive())
    time.sleep(1)
    print(p.is_alive())
True
False

需要强调的一点就是terminate()会终止进程,但是不是立马就会将其回收

所以紧接着is_alive()也可能会返回True

隔一段时间再看,就返回的是False

这里提到了一个名词:僵尸进程,其实还有个孤儿进程

僵尸进程:

主进程还没结束的时候退出的子进程就是僵尸进程

任何一个子进程在结束之后并不会马上消失掉,而是要留下一个称为僵尸进程的数据结构,等待父进程处理

这是每个子进程在结束时都要经过的阶段,如果子进程在结束之后,父进程没有来得及处理

那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的

如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,应当避免

孤儿进程:

一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程

孤儿进程将被init进程所收养,并由init进程对它们完成状态收集工作

孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了init进程身上

init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作

每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为ini

这样,当一个孤儿进程凄凉地结束了其生命周期的时候

init进程就会代表党和政府出面处理它的一切善后工作,因此孤儿进程并不会有什么危害


*****
*****

~~并发编程(四):进程方法~~

原文地址:https://www.cnblogs.com/jevious/p/11388062.html

时间: 2024-10-08 22:57:33

~~并发编程(四):进程方法~~的相关文章

并发编程之进程与线程

并发编程之进程与线程 2.1 线程与进程 2.1.1 进程 2.1.2 线程 2.1.3 二者对比 2.2 并行与并发 2.3 应用 2.1 线程与进程 2.1.1 进程 程序指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存.在指令运行过程中还需要用到磁盘.网络等设备.进程就是用来加载指令.管理内存.管理IO的. 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程. 进程就可以视为程序的一个实例.大部分程序可以同时运行多个实例进程(例如记

Java并发编程:进程和线程

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

走近并发编程之一 进程和线程

并发与并行,进程与线程不仅是操作系统中及其重要的概念,也是并发编程入门 必须要理解的核心知识. 什么是并发?并发与并行的区别 顺序编程:程序中的所有事物在任意时刻都只能执行一个步骤 并发:在同一时间段内,需要处理多个任务,而在每个时间点又只能处理一个,这就是并发. 假设我们要把多个任务分配给处理机,如果这台机器有多个处理器,显然可以同时执行这些任务,这就是并行. 不同于并行,并发的目的旨在最大限度的提高程序在单处理器上的效率.前者是在物理上的同时发生,而并发是在逻辑上的同时发生.如图,如果要在同

Go并发编程(四)

并发基础 多进程 多线程 基于回调的非阻塞/异步IO 协程 协程 与传统的系统级线程和进程相比,协程的最大优势在于其"轻量级",可以轻松创建上百万个而不会导致系统资源衰竭, 而线程和进程通常最多也不能超过1万个.这也是协程也叫轻量级线程的原因.多数语言在语法层面并不直接支持协程,而是通过库的方式支持,但用库的方式支持的功能也并不完整,比如仅仅提供轻量级线程的创建.销毁与切换等能力.如果在这样的轻量级线程中调用一个同步 IO 操作,比如网络通信.本地文件读写,都会阻塞其他的并发执行轻量级

9)网络并发 编程、进程、线程和协程

并发网络 Server: #!/usr/bin/env python#-*-conding:utf-8-*-import socketsk = socket.socket()sk.bind(('127.0.0.1',9009))sk.listen()conn,addr = sk.accept()conn.send(b'heooo')msg = conn.recv(1024)print(msg)conn.close()sk.close() Client: #!/usr/bin/env python

15.python并发编程(线程--进程--协程)

一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完成(2)数据集:是程序在执行过程中所需要使用的一切资源(3)进程控制块:用来记录进程外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志.3.进程的作用:是想完成多任务并发,进程之间的内存地址是相互独立的二.线程:1.定义:最小的执行单位,线程的出现是为了

Python并发编程之进程2

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

Java 并发编程(四):如何保证对象的线程安全性

本篇来谈谈 Java 并发编程:如何保证对象的线程安全性. 01.前言 先让我吐一句肺腑之言吧,不说出来会憋出内伤的.<Java 并发编程实战>这本书太特么枯燥了,尽管它被奉为并发编程当中的经典之作,但我还是忍不住.因为第四章"对象的组合"我整整啃了两周的时间,才啃出来点肉丝. 读者朋友们见谅啊.要怪只能怪我自己的学习能力有限,真读不了这种生硬无趣的技术书.但是为了学习,为了进步,为了将来(口号喊得有点大了),只能硬着头皮上. 请随我来,我尽量写得有趣点. 02.线程安全类

python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)

9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于IO密集型 进程池: from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor import time,os,random ? def task(x): print('%s 接客' %os.getpid()) time.

Python并发编程之进程

一.理论概念 1.定义 进程(Process 也可以称为重量级进程)是程序的一次执行.在每个进程中都有自己的地址空间.内存.数据栈以及记录运行的辅助数据,它是系统进行资源分配和调度的一个独立单位. 2.并行和并发 并行:并行是指多个任务同一时间执行: 并发:是指在资源有限的情况下,两个任务相互交替着使用资源: 3.同步和异常 同步是指多个任务在执行时有一个先后的顺序,必须是一个任务执行完成另外一个任务才能执行: 异步是指多个任务在执行时没有先后顺序,多个任务可以同时执行: 4.同步/异步/阻塞/