python多进程

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

python多进程

进程简介

进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;用户进程就不必我多讲了吧,所有由你启动的进程都是用户进程。进程是操作系统进行资源分配的单位。
在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。

进程和线程

进程(process)和线程(thread)
单个CPU一次只能运行一个任务;在任一时刻,CPU总是运行一个进程,其他进程处于非运行状态;
一个进程可以包含多个线程;
进程没有任何共享状态,进程修改的数据,改动仅限于该进程内;
一个进程的内存空间是共享的,每个线程都可以使用这些共享内存;
一个线程使用某些共享内存时,其他线程必须等它结束才能使用这一块内存;防止多个线程同时读写某一块内存区域,采用互斥锁(Mutual exclusion,缩写Mutex);
某些内存区域只能供给固定数目的线程使用,此时通过信号量(Semaphore)保证多个线程不会互相冲突;
多进程形式,运行多个任务同时运行;多线程形式,允许单个任务分成不同的部分运行;
多线程使用的是cpu的一个核,适合io密集型;
多进程使用的是cpu的多个核,适合运算密集型。
在linux中可以使用ps -efL查看进程和线程ID。以memcached进程为例,输出结果如下

1
2
3
4
5
6
7
8
9
10
11
12
[root@VM_0_4_centos ~]# ps -efL |grep memcached
root     24421     1 24421  0   10 May19 ?        00:00:03 memcached -d -u root
root     24421     1 24422  0   10 May19 ?        00:00:01 memcached -d -u root
root     24421     1 24423  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24424  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24425  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24426  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24427  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24428  0   10 May19 ?        00:00:00 memcached -d -u root
root     24421     1 24429  0   10 May19 ?        00:00:09 memcached -d -u root
root     24421     1 24430  0   10 May19 ?        00:00:00 memcached -d -u root
root     32169 31101 32169  0    1 23:23 pts/0    00:00:00 grep --color=auto memcached

 

第一行UID(用户ID),第二行为PID(进程ID),第三行PPID(父进程ID),第四行LWP(线程ID)。
从示例可以看出,进程24421子进程有10个,对应线程ID分别为24421-24430。

multiprocess

python中的多线程无法利用多核优势,若要充分使用多核CPU资源,在python中大部分情况使用多进程。python提供了非常好用的多进程包multiprocessing。
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。
multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

Process类

创建一个Process对象

1
p = multiprocessing.Process(target=worker_1, args=(2, ))

 

  • 参数
    target:函数名字
    args:函数需要的参数,以tuple的形式传入(单个元素的tuple必须有逗号)

  • 方法
    p.is_alive() 判断进程p是否存活,是返回True
    p.run() 启动进程,它去调用target指定的函数
    p.start() 启动进程,它会自动调用run方法,推荐使用start
    p.join(timeout) 主线程等待p终止(主线程处于等的状态,p处于运行状态)。p.join只能join使用start开启的进程,不能join使用run开启的进程
    p.terminate() 强制进程p退出,不会进行任何清理操作,如果p创建了子进程,该子进程就变成了僵尸进程

  • 属性
    p.name 进程的名字
    p.pid 进程的pid
    p.daemon 默认为False,如果设置为True代表p为后台运行的守护进程,当p的父进程终止时p也随之终止,并且设置为True后,p不能创建自己的新进程,必须在p.start()之前设置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import multiprocessing
    import timedef worker(args, interval):print("start worker {0}".format(args))time.sleep(interval)print("end worker {0}".format(args))def main():print("start main")p1 = multiprocessing.Process(target=worker, args=(1, 1))p2 = multiprocessing.Process(target=worker, args=(2, 2))p3 = multiprocessing.Process(target=worker, args=(3, 3))p1.start()p2.start()p3.start()print("end main")if __name__ == '__main__':main()

输出结果

1
2
3
4
5
6
7
8
start main
end main
start worker 1
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

 

multprocessing用到的两个方法
cpu_count():统计cpu总数
active_children():获得所有子进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import multiprocessing
import timedef worker(args, interval):print("start worker {0}".format(args))time.sleep(interval)print("end worker {0}".format(args))def main():print("start main")p1 = multiprocessing.Process(target=worker, args=(1, 1))p2 = multiprocessing.Process(target=worker, args=(2, 2))p3 = multiprocessing.Process(target=worker, args=(3, 3))p1.start()p1.join(timeout=0.5)    #此处保证了p1优先执行p2.start()p3.start()print("the number of CPU is: {0}".format(multiprocessing.cpu_count()))for p in multiprocessing.active_children():print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid))print("end main")if __name__ == '__main__':main()

 

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
start main
start worker 1
the number of CPU is: 4
The name of active children is: Process-1, pid is: 25360 is alive
The name of active children is: Process-2, pid is: 24500 is alive
The name of active children is: Process-3, pid is: 26100 is alive
end main
start worker 3
start worker 2
end worker 1
end worker 2
end worker 3

 

lock组件

当我们用多进程来读写文件的时候,如果一个进程是写文件,一个进程是读文件,如果两个文件同时进行,肯定是不行的,必须是文件写结束以后,才可以进行读操作。或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就要有一个锁机制进行控制。
下面使用2个进程分别进行+1+3操作为例

  • 不加锁
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import time
    import multiprocessingdef add(value, number):print("start add{0} number= {1}".format(value, number))for i in range(1, 3):number += valuetime.sleep(0.3)print("number = {0}".format(number))if __name__ == '__main__':print("start main")number = 0p1 = multiprocessing.Process(target=add, args=(1, number))p3 = multiprocessing.Process(target=add, args=(3, number))p1.start()p3.start()print("end main")

输出结果

1
2
3
4
5
6
7
8
start main
end main
start add1 number= 0
start add3 number= 0
number = 1
number = 3
number = 2
number = 6

 

  • 加锁
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import time
    import multiprocessingdef add(lock, value, number):with lock:print("start add{0} number= {1}".format(value, number))for i in range(1, 3):number += valuetime.sleep(0.3)print("number = {0}".format(number))if __name__ == '__main__':print("start main")number = 0lock = multiprocessing.Lock()p1 = multiprocessing.Process(target=add, args=(lock, 1, number))p3 = multiprocessing.Process(target=add, args=(lock, 3, number))p1.start()p3.start()print("end main")

输出结果

1
2
3
4
5
6
7
8
start main
end main
start add1 number= 0
number = 1
number = 2
start add3 number= 0
number = 3
number = 6

 

锁的获取可以使用lock.acquire()获取,lock.release()释放

1
2
3
4
5
6
7
8
9
10
11
12
13
def add(lock, value, number):lock.acquire()print("start add3 number= {0}".format(number))try:for i in range(1, 5):number += valuetime.sleep(0.3)print("number = {0}".format(number))except Exception as e:raise efinally:lock.release()pass

 

共享内存

一般变量在进程之间是没法进行通讯的,但是multiprocessing提供了ValueArray模块,可以在不同的进程中使用同一变量。ValueArray结构内部都实现了锁机制,因此多进程是安全的。
Value和Array都需要设置其中存放值的类型,d是double类型,i是int类型。类型设置和array模块的值类似,更多的类型可以点击array — Efficient arrays of numeric values查看。
上面的示例中,两个进程执行后number结果分别为2和6,假如两个进程可以共享变量,name输出结果将会是8。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import multiprocessing
from multiprocessing import Valuedef add(value, number):print("start add{0} number= {1}".format(value, number.value))for i in range(1, 3):number.value += valueprint("number = {0}".format(number.value))if __name__ == '__main__':print("start main")number = Value('d', 0)    #使用Value创建变量p1 = multiprocessing.Process(target=add, args=(1, number))p3 = multiprocessing.Process(target=add, args=(3, number))p1.start()p3.start()print("end main")

 

输出结果

1
2
3
4
5
6
7
8
start main
end main
start add1 number= 0.0
start add3 number= 0.0
number = 1.0
number = 4.0
number = 5.0
number = 8.0

 

number最终结果是8,但是具体输出结果每次执行可能存在差异。

更多关于multiprocessing的内容可以点击multiprocessing — Process-based parallelism查看官方介绍。

Share

转载于:https://my.oschina.net/u/3803404/blog/1815848

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

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

相关文章

halcon彩色图像颜色处理算子,持续更新

目录apply_color_trans_lutcfa_to_rgbtrans_to_rgbclear_color_trans_lutcreate_color_trans_lutgen_principal_comp_translinear_trans_colorprincipal_comprgb1_to_grayrgb3_to_graytrans_from_rgbapply_color_trans_lut 功能:申请使用颜色查找表。 cfa_to_rgb …

夺命雷公狗---node.js---20之项目的构建在node+express+mongo的博客项目5mongodb在项目中实现添加数据...

我们上一步就引入了mongodb了,那么下一步就要开始写添加数据了,不过有个前提是先将表单的数据处理好: 最基本的这部现在已经成功了,因为最基本的这步就是先将表单处的提交方式和提交地址给处理好,这里和PHP的基本上是一…

重新绑定ItemsSource先设置ItemsSource = null;的原因

即报错信息为:在使用 ItemsSource 之前,项集合必须为空。原因:Items和ItemSource,只能有一个生效,想用其中一个,另一个必须是空。重新绑定ItemSource,虽然绑定的集合对象Clear了,但是…

敏捷开发学习

Scrum 敏捷开发,绩效管理,团队管理,企业管理,ASP.net MVC 敏捷开发 培训|咨询 工具开发 课题研讨 http://blog.csdn.net/cheny_com/article/category/794542 http://blog.csdn.net/vincetest/article/category/650747 http://blog…

Git commit后,本地代码丢失解决方法

问题描述: 提交代码时,rebase了两次,本地代码丢失了,吓得我差点跳起来。解决方法如下: 1、执行命令: git reflog d6ea731 (HEAD -> dev, origin/dev, master) HEAD{0}: checkout: moving from master to…

Edges图像边缘处理halcon算子,持续更新

目录close_edgesclose_edges_lengthderivate_gaussdiff_of_gaussedges_coloredges_color_sub_pixedges_imageedges_sub_pixfrei_ampfrei_dirhighpass_imageinfo_edgeskirsch_ampkirsch_dirlaplacelaplace_of_gaussprewitt_ampprewitt_dirrobertsrobinson_amprobinson_dirsobel_…

Android存储数据方式

可以查看Android开发文档中的:/docs/guide/topics/data/data-storage.html Android provides several options for you to save persistent application data. The solution you choose depends on your specific needs, such as whether the data should be privat…

防止cpu 一直被占用 sleep(0) 和 yield

在java的Thread类中有两个有用的函数,sleep和yield,sleep就是线程睡眠一定的时间,也就是交出cpu一段时间,yield用来暗示系统交出cpu控制权。这两个函数在多线程开发的时候特别有用,可以合理的分配cpu,提高程…

做一个有胆识的有为青年

1、一个年轻人,如果在这四年的时间里,没有任何想法,他这一生,就基本这个样子,没有多大改变了。 2、成功者就是胆识加魄力,曾经在火车上听人谈起过温州人的成功,说了这么三个字,“胆…

jstack应用-查找CPU飚高的原因

场景 在系统上线后,经常会遇到运维的同学跑过来说:“这次发版后,cpu线程使用率到一场,到100%了”。这时候不要慌,可以使用堆转储来分析到底是哪个线程引起的。 查找元凶 [rootjava_mofei_01 test]# top Mem: 16333644…

Enhancement增强图形halcon算子,持续更新

目录coherence_enhancing_diffemphasizeequ_histo_imageilluminatemean_curvature_flowscale_image_max_shock_filtercoherence_enhancing_diff 功能:执行一个图像的一个一致性增强扩散。 emphasize 功能:增强图像对比度。 equ_histo_image 功能&am…

音频中采样位数,采样率,比特率的名词解释(转)

采样位数(采样大小): 采样位数可以理解为采集卡处理声音的解析度。这个数值越大,解析度就越高,录制和回放的声音就越真实。我们首先要知道:电脑中的声音文件是用数字0和1来表示的。所以在电脑上录音的本质就…

WebSocket实时异步通信

WebSocket实时异步通信 【一】WebSocket简介 WebSocket是HTML5推出一个协议规范,用来B/S模式中服务器端和客户端之间进行实时异步通信。 众所周知,传统的HTTP协议中,服务器端和客户端通信只能是在客户端发送一个请求之后,服务器端…

多线程和多进程的区别(小结)

分类: linux 2009-06-19 09:33 11501人阅读 评论(15) 收藏 举报 很想写点关于多进程和多线程的东西,我确实很爱他们。但是每每想动手写点关于他们的东西,却总是求全心理作祟,始终动不了手。 今天终于下了决心,写点东西…

redis-cli使用密码登录

redis-cli使用密码登录 注意IP地址要写正确! 学习了: https://blog.csdn.net/lsm135/article/details/52932896 https://blog.csdn.net/zyz511919766/article/details/42268219 https://zhidao.baidu.com/question/756651357338691604.html 登录后 auth pass 或者 r…

FFT快速傅式变换算法halcon算子,持续更新

目录convol_fftconvol_gaborcorrelation_fftdeserialize_fft_optimization_dataenergy_gaborfft_genericfft_imagefft_image_invgen_bandfiltergen_bandpassgen_derivative_filtergen_filter_maskgen_gaborgen_gauss_filtergen_highpassgen_lowpassgen_mean_filtergen_sin_band…

仿照vue实现简易的MVVM框架(一)

代码github地址: https://github.com/susantong/myMVVM 主要的方法有: compile 深度遍历前端界面的节点,将其复制进一个addQuene队列中pasers 遍历所有的节点,并将节点包装成一个含有本节点、自定义属性及属性值的对象。要想实现双…

tomcat 启动时内存溢出

在tomcat_home/bin目录下找到catalina.bat,用文本编辑器打开,加上下面一行: set JAVA_OPTS -Xms1024M -Xmx1024M -XX:PermSize256M -XX:MaxNewSize256M -XX:MaxPermSize256M 解释一下各个参数: -Xms1024M:初始化堆内存…

@angular/platform-browser-dynamic

/** experimental */ export declare class JitCompilerFactory implements CompilerFactory {createCompiler(options?: CompilerOptions[]): Compiler; }export declare const platformBrowserDynamic: (extraProviders?: StaticProvider[] | undefined) > PlatformRef;…

牛人项目失败的总结

tom_lt: 遇到的失败项目比较多!让人郁闷!! 仔细分析原因,主要在于: 1.项目开始需求不明确。领导决定动手,就开始启动项目,造成和客户需要差距太大,导致失败; 2.需求变更没…