python多进程(一)

 

操做系统进程


Unix/Linux操做系统提供了一个fork()系统调用,它很是特殊。普通的函数调用,调用一次,返回一次,可是fork()调用一次,返回两次,由于操做系统自动把当前进程(称为父进程)复制了一份(称为子进程),而后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样作的理由是,一个父进程能够fork出不少子进程,因此,父进程要记下每一个子进程的ID,而子进程只须要调用getppid()就能够拿到父进程的ID。
进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程能够分为系统进程和用户进程。凡是用于完成操做系统的各类功能的进程就是系统进程,它们就是处于运行状态下的操做系统自己。全部由你启动的进程都是用户进程。
通俗地讲,在操做系统的管理下,全部正在运行的进程轮流使用CPU,每一个进程容许占用CPU的时间很是短(好比10毫秒),这样用户根本感受不出来CPU是在轮流为多个进程服务,就好象全部的进程都在不间断地运行同样。但实际上在任何一个时间内有且仅有一个进程占有CPU。python

 

多进程


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

Multiprocessing支持子进程,通讯,共享数据,执行不一样形式的同步,提供了Process,Pipe, Lock等组件。函数

 

Process

建立一个Process对象ui

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

target = 函数名字
args = 函数须要的参数,以tuple的形式传入
注意: 单个元素的tuple的表现形式(元素,)有一个逗号spa

multprocessing用到的两个方法
cpu_count()          统计cpu总数
active_children()   得到全部子进程操作系统

 

Process的对象经常使用方法

is_alive()    判断进程是否存活
run()           启动进程
start()         启动进程,会自动调用run方法,这个经常使用
join(timeout) 等待进程结束或者直到超时线程

 

Process的经常使用属性

name 进程名字
pid 进程的pidcode

 

相关代码示例

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()

结果:
start main
end main
start worker 1
start worker 3
start worker 2
end worker 1
end worker 2
end worker 3

 

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 进程的pidorm

 

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()

结果:
start main
start worker 1
the number of CPU is: 4
The name of active children is: Process-3, pid is: 9056 is alive
The name of active children is: Process-2, pid is: 5844 is alive
The name of active children is: Process-1, pid is: 8428 is alive
end main
start worker 2
start worker 3
end worker 1
end worker 2
end worker 3

建立子进程时,只须要传入一个执行函数和函数的参数,建立一个Process实例,用start()方法启动,这样建立进程比fork()还要简单。对象

 

Lock组件


当咱们用多进程来读写文件的时候,若是一个进程是写文件,一个进程是读文件,若是两个文件同时进行,确定是不行的,必须是文件写结束之后,才能够进行读操做。或者是多个进程在共享一些资源的时候,同时只能有一个进程进行访问,那就要有一个锁机制进行控制。

当多个进程须要访问共享资源的时候,Lock能够用来避免访问的冲突。主要用到了lock.acquire() 和lock.release()

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()
        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")

结果:
start main
end main
start add3 number= 0
number = 3
number = 6
number = 9
number = 12
start add1 number= 0
number = 1
number = 2
number = 3
number = 4

 

共享内存


python的multiprocessing模块也给咱们提供了共享内存的操做。
通常的变量在进程之间是无法进行通信的,multiprocessing给咱们提供了Value和Array模块,他们能够在不通的进程中共同使用,Value 和 Array 都须要设置其中存放值的类型,d 是 double 类型,i 是 int 类型。

import time

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
相关文章
相关标签/搜索