python 多线程和多进程
一、多进程
1.概念
进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;用户进程就不必我多讲了吧,所有由你启动的进程都是用户进程。进程是操作系统进行资源分配的单位。
它的思想简单介绍如下:在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。
2.多进程和多线程的区别:
多线程使用的是cpu的一个核,适合io密集型
多进程使用的是cpu的多个核,适合运算密集型
组件
Python提供了非常好用的多进程包,multiprocessing,我们在使用的时候,只需要导入该模块就可以了。
Multiprocessing支持子进程,通信,共享数据,执行不同形式的同步,提供了Process,Pipe, Lock等组件
看个小例子:
import multiprocessing
import time
def worker(args, interval):
print("start worker {0}".format(args))
time.sleep(s)
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
(2)multprocessing用到的两个方法
cpu_count() 统计cpu总数
active_children() 获得所有子进程
在看一个小例子:
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()
3.Lock组件
当我们用多进程来读写文件的时候,如果一个进程是写文件,一个进程是读文件,如果两个文件同时进行,肯定是不行的,必须是文件写结束以后,才可以进行读操作。或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就要有一个锁机制进行控制。
需求:
一个进程写入一个文件,一个进程追加文件,一个进程读文件,同时启动起来
我们可以通过进程的join()方法来实现,但是为了学习Lock,用Lock来实现。
先看不加锁程序,在看加锁程序,最后比较两个程序的区别
例子:
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()
pass
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")
例子2:
from multiprocessing import Array, Process
def woker(arr):
for i in range(len(arr)):
arr[i] = -arr[i]
if __name__ == '__main__':
arr = Array('i', [x for x in range(10)])
print(arr)
print(arr[:])
p = Process(target=woker, args=(arr,))
p.start()
p.join()
print(arr[:])
例子3:
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")
help(Value)