Python多进程开发之如何轻松突破GIL瓶颈

 更新时间:2025年06月23日 08:11:55   作者:烛阴  
这篇文章主要来和大家详细介绍一下Python多进程开发的相关知识,看看它是如何绕过GIL全局解释器锁的,感兴趣的小伙伴可以跟随小编一起学习一下

1. 为啥要用多进程?先认清GIL

Python多线程为何没法加速CPU密集型任务?因为GIL(全局解释器锁):在主流的CPython解释器中,无论多少线程归根结底同时只有一个线程在执行Python字节码,严重影响CPU计算性能的并行。

多进程机制完美绕开了GIL:每个进程拥有自己的Python解释器和内存空间,真正多核、多CPU并行执行,CPU密集型任务大大提速!

2. Python多进程基础用法:multiprocessing库

Python 内置标准库 multiprocessing,API与threading非常类似,上手容易。

2.1 Proces介绍

Process([group [, target [, name [, args [, kwargs]]]]])

  • target 表示调用对象
  • args 表示调用对象的位置参数元组
  • kwargs 表示调用对象的字典
  • name 为别名
  • group 实质上不使用

2.2 Hello,多进程

from multiprocessing import Process
import os

def worker():
    print('子进程PID:', os.getpid())

if __name__ == '__main__':
    p = Process(target=worker)
    p.start()
    p.join()
    print('主进程结束')

注意! Windows下多进程要写在 if __name__ == '__main__': 保护块内,否则会无限递归启动进程。

2.3 多进程并行计算

from multiprocessing import Process
import time

def task(name):
    print(f'{name} 开始')
    time.sleep(2)
    print(f'{name} 结束')

if __name__ == '__main__':
    proc_list = []
    for i in range(3):
        p = Process(target=task, args=(f'进程{i+1}',))
        p.start()
        proc_list.append(p)
    for p in proc_list:
        p.join()
    print('所有子进程结束')

多个进程可并发分担任务,真正多核利用!

2.4 子进程类实现(面向对象)

import multiprocessing
import time

class ClockProcess(multiprocessing.Process):
    def __init__(self, interval):
        multiprocessing.Process.__init__(self)
        self.interval = interval

    def run(self):
        n = 5
        while n > 0:
            print("当前时间: {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1


if __name__ == '__main__':
    p = ClockProcess(3)
    p.start()

3. 进阶:进程池批量并行(Process Pool)

大量任务并发时,手动管理进程很麻烦,用Pool池自动分配和收集结果,极大提升效率!

from multiprocessing import Pool
import os, time

def square(n):
    print('计算', n, '在进程', os.getpid())
    time.sleep(1)
    return n * n

if __name__ == '__main__':
    with Pool(processes=3) as pool:
        results = pool.map(square, range(5))
    print('返回结果:', results)

比循环创建 Process 简洁得多,还能自动分配CPU,每个子进程并发执行给定任务。

4. 多进程间数据:通信与共享

  • 每个进程独立内存,不能像多线程那样直接共享变量
  • 多进程用队列(Queue)、管道(Pipe)或特殊共享对象实现

4.1 用队列 Queue 通信(推荐)

from multiprocessing import Process, Queue

def producer(q):
    for i in range(5):
        q.put(i)
    q.put(None)  # 发送结束标记

def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print('消费:', item)

if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer, args=(q,))
    p2 = Process(target=consumer, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

4.2 共享内存变量:Value 与 Array

from multiprocessing import Process, Value, Array

def worker(val, arr):
    val.value += 10
    for i in range(len(arr)):
        arr[i] *= 2

if __name__ == '__main__':
    num = Value('i', 5)                # int类型共享变量
    arr = Array('i', [1, 2, 3, 4])     # 数组
    p = Process(target=worker, args=(num, arr))
    p.start()
    p.join()
    print('num =', num.value)
    print('arr =', list(arr))

5. 多进程安全:锁机制

多进程也需防止竞争条件,通过 Lock/Manager 加锁同步。

from multiprocessing import Process, Lock, Value

def add(lock, counter):
    for _ in range(100000):
        with lock:
            counter.value += 1

if __name__ == '__main__':
    lock = Lock()
    counter = Value('i', 0)
    procs = [Process(target=add, args=(lock, counter)) for _ in range(4)]
    for p in procs:
        p.start()
    for p in procs:
        p.join()
    print('结果:', counter.value)

6. 多进程vs多线程,该如何选?

  • CPU密集(数值计算/图像处理/大数据科学):用多进程“跑满CPU”突破GIL
  • IO密集(爬虫/网络/磁盘/数据库交互):多线程即可,更省内存和切换开销

到此这篇关于Python多进程开发之如何轻松突破GIL瓶颈的文章就介绍到这了,更多相关Python GIL内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 用Python爬取英雄联盟的皮肤详细示例

    用Python爬取英雄联盟的皮肤详细示例

    大家好,本篇文章主要讲的是用Python爬取英雄联盟的皮肤详细示例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 利用ctypes提高Python的执行速度

    利用ctypes提高Python的执行速度

    这篇文章给大家介绍了如何利用ctypes提高Python的执行速度,对大家学习使用python具有一定的参考借鉴价值。有需要的朋友们一起来看看吧。
    2016-09-09
  • Python 网页解析HTMLParse的实例详解

    Python 网页解析HTMLParse的实例详解

    这篇文章主要介绍了Python 网页解析HTMLParse的实例详解的相关资料,python里提供了一个简单的解析模块HTMLParser类,使用起来也是比较简单的,解析语法没有用到XPath类似的简洁模式,需要的朋友可以参考下
    2017-08-08
  • PyQt5通过信号实现MVC的示例

    PyQt5通过信号实现MVC的示例

    这篇文章主要介绍了PyQt5通过信号实现MVC的示例,帮助大家更好的理解和使用pyqt5,感兴趣的朋友可以了解下
    2021-02-02
  • Python3基于print打印带颜色字符串

    Python3基于print打印带颜色字符串

    这篇文章主要介绍了Python3使基于print打印带颜色字符串,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 王纯业的Python学习笔记 下载

    王纯业的Python学习笔记 下载

    这篇文章主要介绍了王纯业的Python学习笔记 下载
    2007-02-02
  • Python编程中归并排序算法的实现步骤详解

    Python编程中归并排序算法的实现步骤详解

    这篇文章主要介绍了Python编程中归并排序算法的实现步骤详解,归并排序的平均时间复杂度为(n\log n),需要的朋友可以参考下
    2016-05-05
  • python如何读取bin文件并下发串口

    python如何读取bin文件并下发串口

    这篇文章主要介绍了python如何读取bin文件并下发串口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python中numpy 常用操作总结

    python中numpy 常用操作总结

    这篇文章主要介绍了python中numpy常用操作总结,NumPy是Python语言的一个扩充程序库,支持大量高维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库
    2022-09-09
  • 使用python装饰器验证配置文件示例

    使用python装饰器验证配置文件示例

    项目中用到了一个WriteData的函数保存用户填写的配置,为了实现验证用户输入的需求,在不影响接口的使用的前提下,采用了python的装饰器实现,代码片段演示了如何验证WriteData函数的输入参数
    2014-02-02

最新评论