博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多进程
阅读量:4559 次
发布时间:2019-06-08

本文共 5388 字,大约阅读时间需要 17 分钟。

一、多进程

1.1、概念

  进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;用户进程就不必我多讲了吧,所有由你启动的进程都是用户进程。进程是操作系统进行资源分配的单位。它的思想简单介绍如下:

在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。

shell中使用多进程的类型:

#!/bin/bash

testsleep(){
    echo "start sleep"
    sleep 5
    echo "end sleep"
}
echo "start main"
testsleep &            #&后台运行的模式就是使用了多进程的理念
echo "end main"

1.2、多进程和多线程的区别:

  • 多进程使用的是cpu的多个核,适合运算密集型
  • 多线程使用的是cpu的一个核,适合io密集型

1.3、组件

Python提供了非常好用的多进程包,multiprocessing,我们在使用的时候,只需要导入该模块就可以了。Multiprocessing支持子进程,通信,共享数据,执行不同形式的同步,提供了Process,Pipe, Lock等组件

1.4、示例:

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() # p = multiprocessing.Process(target=, args=) # target 指定的是当进程执行时,需要执行的函数 # args 是当进程执行时,需要给函数传入的参数 # 注意: args必须是一个tuple, 特别是当函数需要传入一个参数时 (1,) # p 代表的是一个多进程, # p.is_alive() 判断进程是否存活 # p.run() 启动进程 # p.start() 启动进程,他会自动调用run方法,推荐使用start # p.join(timeout) 等待子进程结束或者到超时时间 # p.terminate() 强制子进程退出 # p.name 进程的名字 # p.pid 进程的pid

1.5、示例:

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) 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.6、Lock组件

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

需求:

一个进程写入一个文件,一个进程追加文件,一个进程读文件,同时启动起来
我们可以通过进程的join()方法来实现,但是为了学习Lock,用Lock来实现。
先看不加锁程序,在看加锁程序,最后比较两个程序的区别

示例:

import time import multiprocessing def add1(lock, value, number): with lock: #这里是第一种调用锁的方法,好处是能自动释放锁 print("start add1 number= {0}".format(number)) for i in range(1, 5): number += value time.sleep(0.3) print("number = {0}".format(number)) def add3(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() if __name__ == '__main__': print("start main") number = 0 lock = multiprocessing.Lock() #这里创建了锁的机制,目的是为了避免进程间无序执行 p1 = multiprocessing.Process(target=add1, args=(lock, 1, number)) p3 = multiprocessing.Process(target=add3, args=(lock, 3, number)) p1.start() p3.start() print("end main")

1.7、共享内存

python的multiprocessing模块也给我们提供了共享内存的操作

一般的变量在进程之间是没法进行通讯的,multiprocessing给我们提供了Value和Array模块,他们可以在不通的进程中共同使用

示例:

import multiprocessing from multiprocessing import Value, Array, Manager def add1(value, number): print("start add1 number= {0}".format(number.value)) for i in range(1, 5): number.value += value print("number = {0}".format(number.value)) def add3(value, number): print("start add3 number= {0}".format(number.value)) try: for i in range(1, 5): number.value += value print("number = {0}".format(number.value)) except Exception as e: raise e if __name__ == '__main__': print("start main") number = Value('d', 0) #这里创建了一个共享内存 p1 = multiprocessing.Process(target=add1, args=(1, number)) p3 = multiprocessing.Process(target=add3, args=(3, number)) p1.start() p3.start() print("end main") 输出结果: start main end main start add1 number= 0.0 number = 1.0 number = 2.0 number = 3.0 number = 4.0 start add3 number= 4.0 number = 7.0 number = 10.0 number = 13.0 number = 16.0 #这里运行的结果也是按照每个进程顺序来的,可以得出的是在共享内存里会默认给每个进程加一个锁,避免进程间乱套

以上实现的数据共享的方式只有两种结构Value和Array。Python中提供了强大的Manage专门用来做数据共享的,其支持的类型非常多,包括,Value, Array,list,dict, Queue, Lock等。

下面看个例子:

from multiprocessing import Process, Manager

def func(dt, lt):
for i in range(10):
key = 'arg' + str(i)
dt[key] = i * i
lt += range(11, 16)
if __name__ == "__main__":
manager = Manager()
dt = manager.dict()
lt = manager.list()
p = Process(target=func, args=(dt, lt))
p.start()
p.join()
print(dt)
print(lt)

 1.8、进程池

  Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程。

示例:

import time import multiprocessing def fun(msg): print("#########start#### {0}".format(msg)) time.sleep(3) print("#########end###### {0}".format(msg)) if __name__ == '__main__': print("start main") pool = multiprocessing.Pool(processes=3) for i in range(1, 7): msg = "hello {0}".format(i) pool.apply_async(fun, (msg,))# 执行时间6s+ # pool.apply(fun, (msg,)) 6*3=18+#执行时间 pool.close()#在调用join之前,要先调用close,否则会报错,close执行完不会有新的进程加入到pool pool.join()#join 是等待所有的子进程结束 print("end main")

1.9、进程池阻塞和非阻塞的区别:

  • Pool.apply_async         非阻塞,定义的进程池进程最大数可以同时执行。
  • Pool.apply                    一个进程结束,释放回进程池,下一个进程才可以开始

 

 

转载于:https://www.cnblogs.com/Jweiqing/p/9064287.html

你可能感兴趣的文章
vsCode 需安装的扩展
查看>>
Arraw function
查看>>
switch和if else的区别和应用
查看>>
浏览器BOM模型
查看>>
Easyui上传文件的问题
查看>>
前端css常用class命名id命名
查看>>
领扣(LeetCode)两句话中的不常见单词 个人题解
查看>>
nginx的location匹配
查看>>
例5-11和例5-12和例5-13
查看>>
无法搜到个例网络
查看>>
利用CSS3制作网页动画
查看>>
熟悉LINUX系统的基本操作
查看>>
[LeetCode] 42. Trapping Rain Water
查看>>
bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法
查看>>
python 全栈开发,Day80(博客系统分析,博客主页展示)
查看>>
手机QQ会员H5加速方案——sonic技术内幕
查看>>
第四周
查看>>
python中的单元测试pyUnit & what is unit test and why
查看>>
c++:资源管理(RAII)、new/delete的使用、接口设计与声明、swap函数
查看>>
第四周作业
查看>>