python多进程的理解 multiprocessing Process join run

news2024/11/15 13:26:34

最近看了下多进程。

一种接近底层的实现方法是使用 os.fork()方法,fork出子进程。但是这样做事有局限性的。比如windows的os模块里面没有 fork() 方法。

windows:

。linux:

另外还有一个模块:subprocess。这个没整过,但从vamei的博客里看到说也同样有局限性。

所以直接说主角吧 --- multiprocessing模块。 multiprocessing模块会在windows上时模拟出fork的效果,可以实现跨平台,所以大多数都使用multiprocessing。

下面给一段简单的代码,演示一下创建进程:

#encoding:utf-8
from multiprocessing import Process
import os, time, random

#线程启动后实际执行的代码块
def r1(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random())

def r2(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random())
    
if __name__ == "__main__":
        print "main process run..."
        p1 = Process(target=r1, args=('process_name1', ))       #target:指定进程执行的函数,args:该函数的参数,需要使用tuple
        p2 = Process(target=r2, args=('process_name2', ))
        
        p1.start()    #通过调用start方法启动进程,跟线程差不多。
        p2.start()    #但run方法在哪呢?待会说。。。
        p1.join()     #join方法也很有意思,寻思了一下午,终于理解了。待会演示。
        p2.join()
        print "main process runned all lines..."

执行结果:

上面提到了两个方法:run 和join

run:如果在创建Process对象的时候不指定target,那么就会默认执行Process的run方法:

#encoding:utf-8
from multiprocessing import Process
import os, time, random

def r():
    print 'run method'
    
if __name__ == "__main__":
        print "main process run..."
        #没有指定Process的targt
        p1 = Process()
        p2 = Process()
        #如果在创建Process时不指定target,那么执行时没有任何效果。因为默认的run方法是判断如果不指定target,那就什么都不做
        #所以这里手动改变了run方法
        p1.run = r
        p2.run = r
        
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print "main process runned all lines..."

另:python源码里,Process.run方法:

执行结果:

可见如果在实例化Process不指定target,就会执行默认的run方法。

还有一个join方法:

最上面演示的代码中,在调用Process的start方法后,调用了两次join方法。这个join方法是干什么的呢?

官方文档的意思是:阻塞当前进程,直到调用join方法的那个进程执行完,再继续执行当前进程。

比如还是刚才的代码,只是把两个join注释掉了:

#encoding:utf-8
from multiprocessing import Process
import os, time, random

def r1(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random())
def r2(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random())

if __name__ == "__main__":
        print "main process run..."
        p1 = Process(target=r1, args=('process_name1', )) 
        p2 = Process(target=r2, args=('process_name2', )) 

        p1.start()
        p2.start()
        #p1.join()
        #p2.join()    
        print "main process runned all lines..."

 执行结果:

 发现主进程不像之前那样,等待两个子进程执行完了,才继续执行。而是启动两个进程后立即向下执行。

为了深刻理解,这次把p2的执行函数里面睡眠时间调大,让他多睡一会,然后保留p1的join,注释掉p2的join,效果更明显:

#encoding:utf-8
from multiprocessing import Process
import os, time, random

def r1(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random())
def r2(process_name):
    for i in range(5):
        print process_name, os.getpid()     #打印出当前进程的id
        time.sleep(random.random()*2)

if __name__ == "__main__":
        print "main process run..."
        p1 = Process(target=r1, args=('process_name1', )) 
        p2 = Process(target=r2, args=('process_name2', )) 

        p1.start()
        p2.start()
        p1.join()
        #p2.join()    
        print "main process runned all lines..."

执行结果:

发现主线程只是等待p1完成了,就会向下执行,而不会等待p2是否完成。

 所以使用多进程的常规方法是,先依次调用start启动进程,再依次调用join要求主进程等待子进程的结束。

然而为什么要先依次调用start再调用join,而不是start完了就调用join呢,如下:

由:

p1.start()
p2.start()
p1.join()

改为:

p1.start()
p1.join()
p2.start()

执行效果:

 发现是先执行完p1,再执行主线程,最后才开始p2。

今天上午一直困惑这个事,现在终于明白了。join是用来阻塞当前线程的,p1.start()之后,p1就提示主线程,需要等待p1结束才向下执行,那主线程就乖乖的等着啦,自然没有执行p2.start()这一句啦,当然就变成了图示的效果了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/131629.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Canvas学习笔记 | 图片操作

图片素材 本篇文章的示例采用下图进行图片操作演示。 图片原始尺寸为:640px * 640px。 绘制图片 在Canvas中,我们使用drawImage()方法绘制图片。drawImage()方法有如下3种调用方式: 1.drawImage(image, dx, dy) 2.drawImage(image, dx, d…

【Android】带你细看Android input系统中ANR的机制

“本文基于Android13源码,分析Input系统的Anr实现原理“ 在文章之前,先提几个问题: 如果在activity任意周期(onCreate,onResume等),同步执行耗时超过5s(ANR时间)的任务,…

JavaWeb06 AJAX 黑马用Axios实现用户名已存在问题? JSON Vue Element

01-AJAX-概述-替换JSP 02-AJAX-快速入门 03-案例-验证用户是否存在 04-Axios-基本使用&请求方式别名(可读性不强) 练习:用Axios替换AJAX实现用户名是否存在功能 就把原来的.html 2.2步换成下面的响应代码即可 为啥就是不行呢????? 05-JSON-概述和基础语法 06-JSON-…

并发编程——4.共享模型之内存

目录4.共享模型之内存4.1.Java 内存模型4.2.可见性4.2.1.退不出的循环4.2.2.解决办法4.2.3.可见性 vs 原子性4.3.终止模式之两阶段终止模式4.3.1.错误思路4.3.2.两阶段终止模式4.4.同步模式之 Balking4.4.1.定义4.4.2.实现4.5.有序性4.5.1.指令级并行原理4.5.2.案例4.6.原理之 …

LVS详解

一、负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是Web应用服务器集群,也可以是数据库服务…

新冠“照妖镜”,体质弱点现原形。你是啥症状?2023年,请好好善待你的身体!

新冠“照妖镜”,体质弱点现原形。你是啥症状? 阳性之后的不同症状,是我们身体发出的【预警信号】。 病毒进入时,最先攻击我们自身最薄弱的地方。 2023年,请好好【善待】你的身体! 症状1 、头疼 出现头痛…

Kurganov-Tadmor二阶中心格式:理论介绍

简介 CFD的核心问题是求解双曲偏微分方程 ∂∂tu(x,t)∂∂xf(u(x,t))0\frac{\partial}{\partial t} u(x, t)\frac{\partial}{\partial x} f(u(x, t))0 ∂t∂​u(x,t)∂x∂​f(u(x,t))0在CFD中,双曲偏微分方程一般使用Godunov型迎风格式求解。但是这种迎风格式往往实…

2022年度学习总结

2022年有焦虑也有成长,记录和总结也是成长的一部分。这一年,我也努力在不确定性中做一些确定的事情,感恩被保护的三年,三年清零抗疫结束,做好自己健康的第一责任人。研一半个学期在网课或者封校中度过,我们…

1.0、Linux-入门概述

1.0、Linux-入门概述 我们为什么要学习 Linux ? Linux诞生了这么多年,以前还喊着如何能取代 Windows 系统,现在这个口号已经小多了,任何事物发展都有其局限性;如同现在国内在搞一个社交软件取代 QQ 、微信 一样&#x…

已解决(Python语法报错)SyntaxError: invalid syntax

已解决(Python语法报错)SyntaxError: invalid syntax 文章目录报错信息报错翻译报错原因解决方法帮忙解决报错信息 粉丝群里面一个小伙伴运行Python代码,但是发生了报错(当时他心里瞬间凉了一大截,跑来找我求助&…

IDEA安装与配置教程

一、下载并安装IDEA 1、下载官网: 下载 IntelliJ IDEA (这里以Windows系统为例,其他系统类似) 2、安装 1、下载完成后,直接点击安装包安装,即可。 2、开始安装,然后下一步 3、可以在此处自定…

算法 - 蓝桥杯并查集题型

目录 合并集合 连通块中点的数量 蓝桥杯2017年第八届真题-合根植物 [蓝桥杯][2019年第十届真题] 修改数组 蓝桥幼儿园 刷了好多题,发现并查集这种思想挺妙的,是时候总结一下了; 作用与基本原理: 套路问题: 用一道…

Mac M1 Pro下载node.js

Mac M1 Pro下载node.js基本信息 Mac M1 Pronode版本:14.20.0npm版本:8.19.3cnpm版本:8.5.1 注意: 我之前是去官网下了最新版本node,但cnpm就是下载不下来,于是查了其他博主的文章,这边通过nvm…

aws codepipeline 配置 ecs 蓝绿部署

参考资料 CI/CD workshop for Amazon ECSTutorial: Create a pipeline with an Amazon ECR source and ECS-to-CodeDeploy deploymentAmazon ECS 计算平台上的部署CodeDeploy AppSpec 文件引用 之前的文章介绍了通过codepipeline对ecs服务进行滚动更新,本文主要介…

Docker 学习总结(78)—— WebAssembly 入门简介

什么是 WebAssembly? WebAssembly 是一种定义二进制指令格式的开放标准,它支持从不同的源语言创建可移植的二进制可执行文件。这些二进制文件可以在各种环境中运行。它起源于 Web,并得到各大主流浏览器的支持。 Wasm 如何在浏览器中工作? …

RCTF-pwn-diary

RCTF-pwn-diary 赛后看了一眼发现给出了源码,https://github.com/ruan777/RCTF2022/blob/main/diary/main.cpp 漏洞是erase的问题 解释一下 add(0) add(1) add(2) delete(1)这样子的话,其实就是把2给删除,把2的内容复制到1中,所…

Base64自定义编码表及破解

什么是Base64 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64并不是安全领域的加密算法,其实Base64只能算是一个编码算法,对数据内容进行编码来适合传输。标准Base64编码解码无需额外信息即完全可逆,即使你自…

基于Python + Django 开发一款学生管理系统(附源码)

文章目录1.开发环境源码分享&技术交流2.项目实战1)创建Django项目2)创建应用3)配置MySQL4)数据模型层创建5)路由配置6)增删改查视图函数7)模板页面创建8)启动web服务1.开发环境 …

最大似然和贝叶斯参数估计

统计生成模型的参数估计 – Maximum Likelihood(ML) 假设参数是某个确定的值,通过使似然度最大求出参数 – Bayesian estimation 假设参数是随机变量,估计参数分布的参数 – 最大似然求出具体的参数,贝叶斯求的是参数的分布 最大似然估计 假…

献给自己技术成长的第三年

年度总结词语:幸运 献给自己技术成长的第三年一、五州一都二、if else量产三、学技术四、用真心五、设计精产六、感恩幸运一、五州一都 1.1-1.12成都、2.23-3.19广州、4.12-7.23苏州、8.12-8.20兰州、8.23-9.20湖州、其余杭州 成都。去年年底出差到成都,…