Python多进程与服务器并发原理及用法实例分析
本文深入解析Python多进程原理及服务器并发实现。涵盖进程与程序区别、并发并行概念、进程状态及创建终止机制。重点讲解multiprocessing模块中Process类的参数用法,并通过多进程Socket服务器代码实例,展示如何利用多核CPU提升并发处理能力。
本文通过具体实例分析Python多进程机制与服务器并发处理的原理及用法,旨在为读者提供参考。
进程
什么是进程
进程是指正在执行的过程或任务,而负责执行这些任务的核心硬件是CPU。
进程与程序的区别
程序仅是一组静态的代码集合,而进程则是程序运行时的动态过程。
并发与并行
无论是并行还是并发,在用户感知层面都表现为“同时”运行。尽管进程或线程被视为任务单位,但实际执行者仍是CPU。由于单个CPU在同一时刻只能执行一个任务,因此需要特定的技术来管理这些任务。
一、并发:表现为伪并行,即看起来是同时运行。单个CPU结合多道技术即可实现并发(并行也属于并发的一种形式)。
二、并行:指真正的同时运行,这通常需要具备多个CPU才能实现。
在单核环境下,可以利用多道技术实现并发;在多核环境下,每个核也可以利用多道技术(多道技术主要针对单核场景设计)。
假设有四个CPU核心和六个任务,同一时间内会有四个任务被执行,分别分配给CPU1、CPU2、CPU3和CPU4。
当任务1遇到I/O操作被迫中断时,操作系统会将CPU1的时间片分配给任务5执行,这就是单核环境下的多道技术。
一旦任务1的I/O结束,操作系统会重新调度它(进程调度及分配给哪个CPU运行由操作系统决定),它可能被分配给四个CPU中的任意一个继续执行。
同步与异步
同步执行:当一个进程执行某个任务时,其他进程必须等待其执行完毕,才能继续执行后续操作。
异步执行:当一个进程执行任务时,其他进程无需等待其完成即可继续执行。当有消息返回时,系统会通知后者进行处理,从而提高执行效率。
例如,打电话属于同步通信,而发送短信属于异步通信。
进程的创建
所有硬件都需要操作系统进行管理,只要有操作系统,就存在进程概念及创建进程的方式。某些专用系统(如微波炉控制器)一旦启动,所有进程即已存在。
对于通用系统(运行多种应用程序),需要在系统运行过程中创建或撤销进程,主要包含四种创建新进程的形式。
1. 系统初始化:在Linux中可使用ps命令查看进程,在Windows中可使用任务管理器。前台进程负责与用户交互,后台进程与用户无关,仅在需要时唤醒的称为守护进程(如电子邮件、Web页面、新闻、打印服务)。
2. 一个进程在运行过程中开启子进程(例如nginx开启多进程,或使用os.fork、subprocess.Popen等)。
3. 用户的交互式请求创建新进程(例如用户双击启动暴风影音)。
4. 批处理作业的初始化(仅应用于大型机的批处理系统)。
无论哪种情况,新进程的创建都是由已存在的进程执行一个用于创建进程的系统调用而完成的:
1. 在UNIX系统中,该系统调用是fork。fork会创建一个与父进程完全相同的副本,两者拥有相同的存储映像、环境字符串和打开文件(在Shell解释器进程中,执行命令会创建一个子进程)。
2. 在Windows系统中,该系统调用是CreateProcess。CreateProcess既处理进程创建,也负责将正确的程序装入新进程。
关于创建的子进程,UNIX和Windows系统的异同
1. 相同点:进程创建后,父进程和子进程拥有各自不同的地址空间(多道技术要求在物理层面实现进程间内存隔离),因此一个进程对其地址空间的修改不会影响另一个进程。
2. 不同点:在UNIX中,子进程的初始地址空间是父进程的一个副本(提示:子进程和父进程可以拥有只读的共享内存区);而对于Windows系统,从开始父进程与子进程的地址空间就是不同的。
进程的终止
1. 正常退出(自愿):例如用户点击交互式页面的关闭按钮,或程序执行完毕后调用系统调用正常退出(在Linux中使用exit,在Windows中使用ExitProcess)。
2. 出错退出(自愿):例如执行python a.py时,文件a.py不存在。
3. 严重错误(非自愿):执行非法指令,如引用不存在的内存地址、1/0除零错误等,可以通过异常捕获机制(try...except...)处理。
4. 被其他进程杀死(非自愿):例如使用kill -9命令强制终止。
一个进程由三种状态组成。

重点来了
Python并发编程之多进程
multiprocessing模块介绍
Python中的多线程无法充分利用多核优势,如果要充分利用多核CPU资源(可通过os.cpu_count()查看),在Python中大部分情况需要使用多进程。Python提供了功能强大的多进程包multiprocessing。
multiprocessing模块用于开启子进程,并在子进程中执行定制任务(如函数),该模块与多线程模块threading的编程接口类似。
multiprocessing模块功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
需要再次强调:与线程不同,进程没有任何共享状态,进程修改的数据仅限制在该进程内部。
Process类的介绍
创建进程的类:
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动)。
强调:
1. 需要使用关键字的方式来指定参数。 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号。
- group参数未使用,值始终为None。
- target表示调用对象,即子进程要执行的任务。
- args表示调用对象的位置参数元组,例如args=(1,2,'egon',)。
- kwargs表示调用对象的字典,例如kwargs={'name':'egon','age':18}。
- name为子进程的名称。
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置。
p.name:进程的名称。
p.pid:进程的pid。
p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)。
p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)。
开启子进程
import time
import random
from multiprocessing import Process
def piao(name):
print('%s piaoing' %name)
time.sleep(random.randrange(1,5))
print('%s piao end' %name)
p1=Process(target=piao,args=('egon',)) #必须加,号
p2=Process(target=piao,args=('alex',))
p3=Process(target=piao,args=('wupeqi',))
p4=Process(target=piao,args=('yuanhao',))
p1.start()
p2.start()
p3.start()
p4.start()
print('主线程')
开启子进程2
import time
import random
from multiprocessing import Process
class Piao(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print('%s piaoing' %self.name)
time.sleep(random.randrange(1,5))
print('%s piao end' %self.name)
p1=Piao('egon')
p2=Piao('alex')
p3=Piao('wupeiqi')
p4=Piao('yuanhao')
p1.start() #start会自动调用run
p2.start()
p3.start()
p4.start()
print('主进程')
socket服务器并发
from socket import *
from multiprocessing import Process
server=socket(AF_INET,SOCK_STREAM)
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1',8080))
server.listen(5)
def talk(conn,client_addr):
while True:
try:
msg=conn.recv(1024)
if not msg:break
conn.send(msg.upper())
except Exception:
break
if __name__ == '__main__': #windows下start进程一定要写到这下面
while True:
conn,client_addr=server.accept()
p=Process(target=talk,args=(conn,client_addr))
p.start()
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python Socket编程技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》。
希望本文所述对大家Python程序设计有所帮助。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









