Python并发机制的实现(一)——多进程

Python并发机制的实现(一) —— 多进程

Unix/Linux系统调用实现多进程(Windows系统不支持)

Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

#coding=utf-8
import os
import time

pid = os.fork()

#子进程
if pid==0:
  while True:
    print "child process {}".format(os.getpid())
    time.sleep(2)
#父进程
else:
  while True:
    print "parent process {}".format(os.getppid())
    time.sleep(2)

运行结果:

parent process 3614
child process 3761
child process 3761
parent process 3614
child process 3761
parent process 3614
^\退出 (核心已转储)

有了fork调用,一个进程在接到新任务时就可以复制出一个子进程来处理新任务,常见的Apache服务器就是由父进程监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。

multiprocessing模块

使用multiprocessing模块可以兼容windows操作系统,具体可见源码中python2.7中multiprocessing下的forking.py

#coding=utf-8
import time
import os
from multiprocessing import Process

def p1():
  while True:
    for i in range(5):
      print 'pro1' + ' ' + str(os.getpid())
      time.sleep(2)

def p2(name):
  while True:
    for i in range(5):
      print name + ' ' + str(os.getpid())
      time.sleep(2)

pro1 = Process()
pro2 = Process(target=p2, args=("pro2",))
#重写run函数为p1
pro1.run = p1
pro2.start()
pro2.start()
pro1.join()
pro2.join()

!注意其中的run函数,在python2.7multiprocessing模块中的源码为

def run(self):
  '''
  Method to be run in sub-process; can be overridden in sub-class
  '''
  #如果参数中传入目标函数则运行目标函数
  if self._target:
    self._target(*self._args, **self._kwargs)

分析源码可知创建进程实例后调用start方法启动线程通过一系列异常检测后将自动调用run方法

join方法是用来等待指定子进程的结束,再结束主进程即父进程,避免僵尸进程的产生

Pool模块(进程池)

Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它.进程池可以让你跑满多核CPU,而且使用方法非常简单.

#coding=utf-8

from multiprocessing import Pool
import time

def f(x):
  for i in range(10):
    print i,'-----------',x
    time.sleep(1)

def main():
  #控制进程池的大小为4个进程(可以自行改动测试)
  pool = Pool(processes=4)
  for x in range(10):
    #添加进程入进程池,注意加"_async",apply为阻塞版本,参数分别为target和args
    result = pool.apply_async(f,(x*10,))
  pool.close()
  pool.join()
  if result.successful():
    print 'successful'

if __name__ == "__main__":
  main()

运行此程序发现每次最多只有四个进程并行执行,运行结果如下:

0 ----------- 0
0 ----------- 10
0 ----------- 20
0 ----------- 30
1 ----------- 0
1 ----------- 10
1 ----------- 30
1 ----------- 20
2 ----------- 0
2 ----------- 10
2 ----------- 20
2 ----------- 30
...
8 ----------- 90
8 ----------- 80
9 ----------- 80
9 ----------- 90
successful

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,10几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,这时候进程池Pool发挥作用的时候就到了。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值