当前位置:首页 > 技术 > 正文内容

多进程机制与实践

访客 技术 2026年7月21日 3

一、核心概念解析

  1. 进程的本质 进程是操作系统中执行任务的基本单位,代表一个正在运行的程序实例。它由代码、数据、状态和资源组成。在单核处理器上,通过多道技术实现多个进程的交替执行,形成伪并发;而在多核系统中,真正实现并行执行。

  2. 程序与进程的区别

  • 程序:静态的代码集合,存储于磁盘。
  • 进程:程序在内存中的动态执行过程,包含运行时状态和资源分配。
  1. 调度策略
  • 先来先服务(FCFS):按请求顺序处理,适合长任务,但不利于短任务响应。
  • 短作业优先(SJF):优先调度预计执行时间最短的任务,提高整体效率。
  • 时间片轮转(RR):将CPU时间划分为固定片段,每个进程轮流使用,确保公平性。
  • 多级反馈队列:设置多个优先级队列,高优先级任务可抢占低优先级任务,动态调整调度策略。
  1. 并发与并行
  • 并发:多个任务在同一时间段内交替执行,用户感知为"同时"进行。
  • 并行:多个任务在不同处理单元上同时执行,需多核或分布式硬件支持。
  • 单核系统可通过多道技术模拟并发,但无法实现真正的并行。
  1. 同步与异步、阻塞与非阻塞 | 概念 | 说明 | |------|------| | 同步 | 函数调用等待结果返回后才继续执行 | | 异步 | 发起调用后立即继续后续操作,结果通过回调通知 | | 阻塞 | 当前线程因等待资源而暂停运行 | | 非阻塞 | 不因等待资源而挂起,可继续执行其他逻辑 |

这些术语用于描述任务执行方式和系统行为模式。

二、进程生命周期管理

  1. 创建方式
  • 系统启动时自动创建初始进程
  • 用户交互触发(如双击应用)
  • 程序内部创建子进程(如PyCharm运行脚本)
  • 批处理系统中批量初始化
  1. 操作系统差异
  • Unix/Linux:使用 fork() 复制父进程,继承全部上下文。
  • Windows:使用 CreateProcess 显式创建新进程并加载目标程序。
  1. 终止类型
  • 正常退出:程序主动关闭
  • 错误退出:运行时异常导致崩溃
  • 严重错误:非法内存访问、除零等致命操作
  • 外部强制终止:通过命令如 kill -9 强制结束

三、进程状态模型

  • 五态模型:创建 → 就绪 → 执行 → 阻塞 → 终止
  • 三态模型:运行 → 就绪 → 阻塞

每种状态反映进程当前所处的执行阶段。

四、Python 多进程编程实践

  1. multiprocessing 模块基础
from multiprocessing import Process

def task(name):
    print(f"任务 {name} 在进程 {os.getpid()} 中执行")
    time.sleep(2)
    print(f"任务 {name} 完成")

if __name__ == '__main__':
    # 启动独立进程(并行)
    p = Process(target=task, args=("A",))
    p.start()
    p.join()  # 主进程等待完成

关键方法:

  • start():启动新进程,异步执行
  • join(timeout):阻塞主进程,直到子进程结束
  • is_alive():检查进程是否仍在运行
  • terminate():强制终止进程(不清理资源)

⚠️ 注意:在 Windows 上必须将进程创建代码置于 if __name__ == '__main__': 块内,防止无限递归创建。

  1. 进程创建方式对比

(1)直接调用 Process

p = Process(target=worker, args=(arg,))
p.start()

适用于快速创建并行任务。

(2)继承 Process 类

class Worker(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(f"{self.name} 开始工作")
        time.sleep(1)
        print(f"{self.name} 完成")

# 使用
w = Worker("Worker-1")
w.start()

适合需要自定义初始化逻辑或重写行为的情况。

  1. 内存隔离特性 各进程拥有独立的内存空间,变量修改不会影响其他进程。
money = 100
def increase():
    global money
    money += 10

p = Process(target=increase)
p.start()
p.join()
print(money)  # 仍为 100,因为副本未共享
  1. 实现高并发服务器
import socket
from multiprocessing import Process

def handle_client(conn):
    while True:
        data = conn.recv(1024)
        if not data: break
        conn.send(data.upper())
    conn.close()

server = socket.socket()
server.bind(('127.0.0.1', 8000))
server.listen(5)

while True:
    conn, addr = server.accept()
    p = Process(target=handle_client, args=(conn,))
    p.start()

每个客户端连接由独立子进程处理,实现真正的并发通信。

  1. join 方法详解
  • 无 join:主进程立即结束,子进程后台运行
  • start 后立即 join:串行执行,等待一个完成再启动下一个
  • 所有 start 后统一 join:并行执行,总耗时取决于最长任务
processes = [Process(target=work, args=(i,)) for i in range(5)]
for p in processes:
    p.start()
for p in processes:
    p.join()  # 并行等待所有完成

推荐使用此模式以最大化并行效率。

  1. 进程属性与监控
  • pid:获取进程唯一标识符
  • ppid:获取父进程编号
  • is_alive():判断是否仍在运行
  • terminate():强制终止进程(注意资源泄漏风险)

示例:

p = Process(target=func)
p.start()
print(p.pid)      # 打印子进程ID
print(os.getppid())  # 打印父进程ID
  1. 调试注意事项
  • terminate()is_alive() 可能仍返回 True,需等待一段时间确认退出。
  • 调试器可能因进程异常终止而失去单步控制能力,建议避免在调试中频繁使用 terminate()

五、补充知识

  • 进程号查看
  • Windows:tasklist | findstr PID
  • Linux:ps aux | grep PID
  • 打印顺序混乱原因:多个进程并发输出,不受主进程控制,输出顺序不可预测。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。