0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Python中多线程和多进程的区别

马哥Linux运维 来源:华为云开发者联盟 2024-10-23 11:48 次阅读

本文分享自华为云社区《Python中的多线程与多进程编程大全【python指南】》,作者:柠檬味拥抱。

Python作为一种高级编程语言,提供了多种并发编程的方式,其中多线程与多进程是最常见的两种方式之一。在本文中,我们将探讨Python中多线程与多进程的概念、区别以及如何使用线程池与进程池来提高并发执行效率。

多线程与多进程的概念

多线程

多线程是指在同一进程内,多个线程并发执行。每个线程都拥有自己的执行栈和局部变量,但共享进程的全局变量、静态变量等资源。多线程适合用于I/O密集型任务,如网络请求、文件操作等,因为线程在等待I/O操作完成时可以释放GIL(全局解释器锁),允许其他线程执行。

多进程

多进程是指在操作系统中同时运行多个进程,每个进程都有自己独立的内存空间,相互之间不受影响。多进程适合用于CPU密集型任务,如计算密集型算法、图像处理等,因为多进程可以利用多核CPU并行执行任务,提高整体运算速度。

线程池与进程池的介绍

线程池

线程池是一种预先创建一定数量的线程并维护这些线程,以便在需要时重复使用它们的技术。线程池可以减少线程创建和销毁的开销,提高线程的重复利用率。在Python中,可以使用concurrent.futures.ThreadPoolExecutor来创建线程池。

进程池

进程池类似于线程池,不同之处在于进程池预先创建一定数量的进程并维护这些进程,以便在需要时重复使用它们。进程池可以利用多核CPU并行执行任务,提高整体运算速度。在Python中,可以使用concurrent.futures.ProcessPoolExecutor来创建进程池。

线程池与进程池的应用示例

下面是一个简单的示例,演示了如何使用线程池和进程池来执行一组任务。


import concurrent.futures
import time


def task(n):
    print(f"Start task {n}")
    time.sleep(2)
    print(f"End task {n}")
    return f"Task {n} result"


def main():
    # 使用线程池
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        results = executor.map(task, range(5))
        for result in results:
            print(result)


    # 使用进程池
    with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
        results = executor.map(task, range(5))
        for result in results:
            print(result)


if __name__ == "__main__":
    main()

在上面的示例中,我们定义了一个task函数,模拟了一个耗时的任务。然后,我们使用ThreadPoolExecutor创建了一个线程池,并使用map方法将任务提交给线程池执行。同样地,我们也使用ProcessPoolExecutor创建了一个进程池,并使用map方法提交任务。最后,我们打印出每个任务的结果。

线程池与进程池的性能比较

4004dea2-904a-11ef-a511-92fbcf53809c.png

虽然线程池与进程池都可以用来实现并发执行任务,但它们之间存在一些性能上的差异。

线程池的优势

轻量级: 线程比进程更轻量级,创建和销毁线程的开销比创建和销毁进程要小。

共享内存: 线程共享同一进程的内存空间,可以方便地共享数据。

低开销: 在切换线程时,线程只需保存和恢复栈和寄存器的状态,开销较低。

进程池的优势

真正的并行: 进程可以利用多核CPU真正并行执行任务,而线程受到GIL的限制,在多核CPU上无法真正并行执行。

稳定性: 进程之间相互独立,一个进程崩溃不会影响其他进程,提高了程序的稳定性。

资源隔离: 每个进程有自己独立的内存空间,可以避免多个线程之间的内存共享问题。

性能比较示例

下面是一个简单的性能比较示例,演示了线程池和进程池在执行CPU密集型任务时的性能差异。


import concurrent.futures
import time


def cpu_bound_task(n):
    result = 0
    for i in range(n):
        result += i
    return result


def main():
    start_time = time.time()


    # 使用线程池执行CPU密集型任务
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        results = executor.map(cpu_bound_task, [1000000] * 3)


    print("Time taken with ThreadPoolExecutor:", time.time() - start_time)


    start_time = time.time()


    # 使用进程池执行CPU密集型任务
    with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
        results = executor.map(cpu_bound_task, [1000000] * 3)


    print("Time taken with ProcessPoolExecutor:", time.time() - start_time)


if __name__ == "__main__":
    main()

在上面的示例中,我们定义了一个cpu_bound_task函数,模拟了一个CPU密集型任务。然后,我们使用ThreadPoolExecutor和ProcessPoolExecutor分别创建线程池和进程池,并使用map方法提交任务。最后,我们比较了两种方式执行任务所花费的时间。

通过运行以上代码,你会发现使用进程池执行CPU密集型任务的时间通常会比使用线程池执行快,这是因为进程池可以利用多核CPU真正并行执行任务,而线程池受到GIL的限制,在多核CPU上无法真正并行执行。

401fa002-904a-11ef-a511-92fbcf53809c.png

当考虑如何实现一个能够同时下载多个文件的程序时,线程池和进程池就成为了很有用的工具。让我们看看如何用线程池和进程池来实现这个功能。

首先,我们需要导入相应的库:

import concurrent.futures
import requests
import time

然后,我们定义一个函数来下载文件:


def download_file(url):
    filename = url.split("/")[-1]
    print(f"Downloading {filename}")
    response = requests.get(url)
    with open(filename, "wb") as file:
        file.write(response.content)
    print(f"Downloaded {filename}")
    return filename

接下来,我们定义一个函数来下载多个文件,这里我们使用线程池和进程池来分别执行:


def download_files_with_thread_pool(urls):
    start_time = time.time()
    with concurrent.futures.ThreadPoolExecutor() as executor:
        results = executor.map(download_file, urls)
    print("Time taken with ThreadPoolExecutor:", time.time() - start_time)


def download_files_with_process_pool(urls):
    start_time = time.time()
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = executor.map(download_file, urls)
    print("Time taken with ProcessPoolExecutor:", time.time() - start_time)

最后,我们定义一个主函数来测试这两种方式的性能:


def main():
    urls = [
        "https://www.example.com/file1.txt",
        "https://www.example.com/file2.txt",
        "https://www.example.com/file3.txt",
        # Add more URLs if needed
    ]


    download_files_with_thread_pool(urls)
    download_files_with_process_pool(urls)


if __name__ == "__main__":
    main()

通过运行以上代码,你可以比较使用线程池和进程池下载文件所花费的时间。通常情况下,当下载大量文件时,使用进程池的性能会更好,因为它可以利用多核CPU实现真正的并行下载。而使用线程池则更适合于I/O密集型任务,如网络请求,因为线程在等待I/O操作完成时可以释放GIL,允许其他线程执行。

这个例子展示了如何利用线程池和进程池来提高并发下载文件的效率,同时也强调了根据任务特点选择合适的并发编程方式的重要性。

并发编程中的注意事项

虽然线程池与进程池提供了方便的并发执行任务的方式,但在实际应用中还需要注意一些问题,以避免出现潜在的并发问题和性能瓶颈。

共享资源的同步

在多线程编程中,共享资源的访问需要进行同步,以避免竞争条件和数据不一致性问题。可以使用锁、信号量等同步机制来保护关键资源的访问。

在多进程编程中,由于进程之间相互独立,共享资源的同步相对简单,可以使用进程间通信(如管道、队列)来传递数据,避免数据竞争问题。

内存消耗与上下文切换

创建大量线程或进程可能会导致内存消耗增加,甚至引起内存泄漏问题。因此,在设计并发程序时需要注意资源的合理利用,避免创建过多的线程或进程。

上下文切换也会带来一定的开销,特别是在频繁切换的情况下。因此,在选择并发编程方式时,需要综合考虑任务的特点和系统资源的限制,以及上下文切换的开销。

异常处理与任务超时

在并发执行任务时,需要注意异常处理机制,及时捕获和处理任务中可能出现的异常,以保证程序的稳定性和可靠性。

另外,为了避免任务阻塞导致整个程序停滞,可以设置任务的超时时间,并在超时后取消任务或进行相应的处理。

最佳实践与建议

在实际应用中,为了编写高效、稳定的并发程序,可以遵循以下一些最佳实践和建议:

合理设置并发度: 根据系统资源和任务特点,合理设置线程池或进程池的大小,避免创建过多的线程或进程。

合理分配任务: 根据任务的类型和特点,合理分配任务到线程池或进程池中,以充分利用系统资源。

注意异常处理: 在任务执行过程中及时捕获和处理异常,保证程序的稳定性和可靠性。

监控与调优: 使用监控工具和性能分析工具对并发程序进行监控和调优,及时发现和解决性能瓶颈和潜在问题。

通过遵循以上最佳实践和建议,可以编写出高效、稳定的并发程序,提高程序的执行效率和性能。同时,也可以避免一些常见的并发编程陷阱和问题,确保程序的质量和可靠性。

总结

本文介绍了在Python中使用线程池和进程池来实现并发编程的方法,并提供了相应的代码示例。首先,我们讨论了多线程和多进程的概念及其在并发编程中的应用场景。然后,我们深入探讨了线程池和进程池的工作原理以及它们之间的性能比较。

在代码示例部分,我们演示了如何使用线程池和进程池来执行多个任务,其中包括下载多个文件的示例。通过比较两种方式执行任务所花费的时间,我们可以更好地了解它们在不同场景下的优劣势。

此外,文章还提供了一些并发编程中的注意事项和最佳实践,包括共享资源的同步、内存消耗与上下文切换、异常处理与任务超时等。这些建议有助于开发者编写高效、稳定的并发程序,提高程序的执行效率和性能。

总的来说,线程池和进程池是Python中强大的工具,能够帮助开发者轻松实现并发编程,并充分利用计算资源。选择合适的并发编程方式,并结合实际场景和任务特点,可以编写出高效、可靠的并发程序,提升应用的性能和用户体验。

链接:https://www.cnblogs.com/huaweiyun/p/18243386

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程语言
    +关注

    关注

    10

    文章

    1927

    浏览量

    34532
  • 多线程
    +关注

    关注

    0

    文章

    277

    浏览量

    19888
  • python
    +关注

    关注

    54

    文章

    4763

    浏览量

    84338
  • 多进程
    +关注

    关注

    0

    文章

    14

    浏览量

    2608

原文标题:一文带你搞清楚Python的多线程和多进程

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    进程线程区别

    )。不管是多进程还是多线程,最终目标都是实现并行执行。 2、多线程的优势前些年多进程多一些,近些年多线程开始用得多。现代操作系统设计时考虑到
    发表于 11-30 14:06

    Python多线程编程原理

    Python多线程类似于同时执行多个不同程序,但其执行过程中和进程还是有区别的,每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口
    发表于 11-22 14:01

    多线程多进程区别

    6.你的数据库一会又500个连接数,一会有10个,你分析一下情况7.udp和tcp的区别8.多线程多进程区别9.有一台web服务器,你选择用多线
    发表于 07-19 07:21

    浅谈多进程多线程的选择

    鱼还是熊掌:浅谈多进程多线程的选择关于多进程多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,
    发表于 08-24 07:38

    python多线程多进程对比

    段可以干多件事,譬如可以边吃饭边看电视;在Python多线程 和 协程 虽然是严格上来说是串行,但却比一般的串行程序执行效率高得很。 一般的串行程序,在程序阻塞的时候,只能干等着,不能去做其他事
    发表于 03-15 16:42

    LINUX系统下多线程多进程性能分析

    采用多进程处理多个任务,会占用很多系统资源(主要是CPU 和内存的使用)。在LINUX ,则对这种弊端进行了改进,在用户态实现了多线程处理多任务。本文系统论述了多线程
    发表于 08-13 08:31 20次下载

    python多线程多进程区别

    Python的设计哲学是“优雅”、“明确”、“简单”。因此,Perl语言中“总是有多种方法来做同一件事”的理念在Python开发者通常是难以忍受的。Python开发者的哲学是“用一种
    发表于 12-01 09:04 6125次阅读
    <b class='flag-5'>python</b><b class='flag-5'>多线程</b>与<b class='flag-5'>多进程</b>的<b class='flag-5'>区别</b>

    如何选好多线程多进程

    关于多进程多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”,这句话应付考试基本上够了,但如果在工作
    的头像 发表于 05-11 16:16 2921次阅读
    如何选好<b class='flag-5'>多线程</b>和<b class='flag-5'>多进程</b>

    多进程多线程的深度比较

    嵌入式Linux中文站,关于多进程多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”。这句话应付考试基本上够了,但如果在工作
    发表于 04-02 14:42 447次阅读

    多进程多线程的基本概念

    ,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程负责IO处理、人机
    发表于 04-02 14:49 733次阅读

    Python多进程学习

    Python 多进程 (Multiprocessing) 是一种同时利用计算机多个处理器核心 (CPU cores) 进行并行处理的技术,它与 Python多线程 (Multith
    的头像 发表于 04-26 11:04 507次阅读

    浅谈Linux网络编程多进程多线程

    在Linux网络编程,我们应该见过很多网络框架或者server,有多进程的处理方式,也有多线程处理方式,孰好孰坏并没有可比性,首先选择多进程还是
    发表于 08-08 16:56 775次阅读
    浅谈Linux网络编程<b class='flag-5'>中</b>的<b class='flag-5'>多进程</b>和<b class='flag-5'>多线程</b>

    关于Python多进程多线程详解

    进程(process)和线程(thread)是操作系统的基本概念,但是它们比较抽象,不容易掌握。关于多进程多线程,教科书上最经典的一句话是“进程
    的头像 发表于 11-06 14:46 782次阅读
    关于<b class='flag-5'>Python</b><b class='flag-5'>多进程</b>和<b class='flag-5'>多线程</b>详解

    Linux系统上多线程多进程的运行效率

    关于多进程多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是CPU调度的最小单位”,这句话应付考试基本上够了,但如果在工作
    的头像 发表于 11-10 10:54 1272次阅读
    Linux系统上<b class='flag-5'>多线程</b>和<b class='flag-5'>多进程</b>的运行效率

    你还是分不清多进程多线程吗?一文搞懂!

    你还是分不清多进程多线程吗?一文搞懂! 多进程多线程是并发编程中常见的两个概念,它们都可以用于提高程序的性能和效率。但是它们的实现方式和使用场景略有不同。 1.
    的头像 发表于 12-19 16:07 510次阅读