进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程能够分为系统进程和用户进程。凡是用于完成操做系统的各类功能的进程就是系统进程,它们就是处于运行状态下的操做系统自己;用户进程就没必要我多讲了吧,全部由你启动的进程都是用户进程。进程是操做系统进行资源分配的单位。
在操做系统的管理下,全部正在运行的进程轮流使用CPU,每一个进程容许占用CPU的时间很是短(好比10毫秒),这样用户根本感受不出来CPU是在轮流为多个进程服务,就好象全部的进程都在不间断地运行同样。但实际上在任何一个时间内有且仅有一个进程占有CPU。html
进程(process)和线程(thread)
单个CPU一次只能运行一个任务;在任一时刻,CPU老是运行一个进程,其余进程处于非运行状态;
一个进程能够包含多个线程;
进程没有任何共享状态,进程修改的数据,改动仅限于该进程内;
一个进程的内存空间是共享的,每一个线程均可以使用这些共享内存;
一个线程使用某些共享内存时,其余线程必须等它结束才能使用这一块内存;防止多个线程同时读写某一块内存区域,采用互斥锁(Mutual exclusion,缩写Mutex);
某些内存区域只能供给固定数目的线程使用,此时经过信号量(Semaphore)保证多个线程不会互相冲突;
多进程形式,运行多个任务同时运行;多线程形式,容许单个任务分红不一样的部分运行;
多线程使用的是cpu的一个核,适合io密集型;
多进程使用的是cpu的多个核,适合运算密集型。
在linux中可使用ps -efL查看进程和线程ID。以memcached进程为例,输出结果以下python
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。linux
python中的多线程没法利用多核优点,若要充分使用多核CPU资源,在python中大部分状况使用多进程。python提供了很是好用的多进程包multiprocessing。
multiprocessing模块用来开启子进程,并在子进程中执行咱们定制的任务(好比函数),该模块与多线程模块threading的编程接口相似。
multiprocessing模块的功能众多:支持子进程、通讯和共享数据、执行不一样形式的同步,提供了Process、Queue、Pipe、Lock等组件。编程
建立一个Process对象centos
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建立了子进程,该子进程就变成了僵尸进程多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import multiprocessing import time def 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() |
输出结果memcached
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 time def 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() |
输出结果ui
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 |
当咱们用多进程来读写文件的时候,若是一个进程是写文件,一个进程是读文件,若是两个文件同时进行,确定是不行的,必须是文件写结束之后,才能够进行读操做。或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就要有一个锁机制进行控制。
下面使用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 multiprocessing def add(value, number): print("start add{0} number= {1}".format(value, number)) for i in range(1, 3): number += value time.sleep(0.3) print("number = {0}".format(number)) if __name__ == '__main__': print("start main") number = 0 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 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 multiprocessing def add(lock, value, number): with lock: print("start add{0} number= {1}".format(value, number)) for i in range(1, 3): number += value time.sleep(0.3) print("number = {0}".format(number)) if __name__ == '__main__': print("start main") number = 0 lock = 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 += value time.sleep(0.3) print("number = {0}".format(number)) except Exception as e: raise e finally: lock.release() pass |
通常变量在进程之间是无法进行通信的,可是multiprocessing提供了Value
和Array
模块,能够在不一样的进程中使用同一变量。Value
和Array
结构内部都实现了锁机制,所以多进程是安全的。
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 Value def add(value, number): print("start add{0} number= {1}".format(value, number.value)) for i in range(1, 3): number.value += value print("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