白骑士的Python教学高级篇 3.1 多线程与多进程

系列目录

上一篇:白骑士的Python教学进阶篇 2.4 高级数据结构

        在现代编程中,提升程序性能和处理能力的常见方法之一是并发编程,通过同时执行多个任务来提高效率。Python中主要有两种并发方式:多线程和多进程。理解它们的概念、差异以及如何在Python中使用这些技术是成为高级Python开发者的重要一步。

线程与进程的概念

        线程:操作系统能够进行运算调度的最小单位,一个进程可以包含一个或多个线程。线程之间共享进程的资源,如内存和文件句柄,但每个线程有自己的栈和寄存器等私有数据。多线程适合I/O密集型任务,因为线程可以在等待I/O操作完成时执行其他任务。

        进程:资源分配的基本单位,一个进程包含了程序的代码、数据、内存空间和资源(如文件句柄、信号等)。每个进程都有自己的独立内存空间,进程间的数据共享需要通过进程间通信(IPC)机制。多进程适合CPU密集型任务,因为每个进程都有独立的内存空间和GIL限制,不会互相干扰。

threading模块

        Python的 ‘threading’ 模块提供了创建和控制线程的方法。使用 ‘threading’ 模块可以轻松地在程序中创建多个线程,实现并发执行。

创建线程

        创建线程的最简单方式是实例化 ‘threading.Thread’ 类,然后调用 ‘start()’ 方法启动线程,例如:

import threadingdef worker():print("Thread is running")# 创建线程
thread = threading.Thread(target=worker)# 启动线程
thread.start()# 等待线程完成
thread.join()

线程同步

        由于线程共享全局变量,因此需要考虑线程同步的问题,以避免竞争条件。‘threading’ 模块提供了多种同步原语,如锁(Lock)、条件变量(Condition)和事件(Event)。

import threading# 创建一个锁对象
lock = threading.Lock()
counter = 0def worker():global counterwith lock:  # 使用锁来确保对共享资源的互斥访问counter += 1threads = [threading.Thread(target=worker) for _ in range(10)]# 启动所有线程
for thread in threads:thread.start()# 等待所有线程完成
for thread in threads:thread.join()print(f"Counter value: {counter}")

multiprocessing模块

        Python的 ‘multiprocessing’ 模块允许创建多个进程,每个进程运行在独立的内存空间中,从而绕过GIL的限制。这使得 ‘multiprocessing’ 模块特别适合CPU密集型任务。

创建进程

        与 ‘threading’ 模块类似,可以通过实例化 ‘multiprocessing.Process’ 类来创建进程,例如:

import multiprocessingdef worker():print("Process is running")# 创建进程
process = multiprocessing.Process(target=worker)# 启动进程
process.start()# 等待进程完成
process.join()

进程间通信

        由于每个进程都有自己的内存空间,进程间通信(IPC)是必须的。‘multiprocessing’ 模块提供了队列(Queue)和管道(Pipe)等IPC机制。

import multiprocessingdef worker(queue):queue.put("Hello from process")# 创建队列
queue = multiprocessing.Queue()# 创建进程
process = multiprocessing.Process(target=worker, args=(queue,))# 启动进程
process.start()# 等待进程完成
process.join()# 从队列中获取数据
print(queue.get())

共享内存

        ‘multiprocessing’ 模块还提供了共享内存的机制,可以通过 ‘Value’ 和 ‘Array’ 实现进程间的数据共享,例如:

import multiprocessingdef worker(shared_counter):with shared_counter.get_lock():  # 获取锁shared_counter.value += 1# 创建共享内存对象
counter = multiprocessing.Value('i', 0)processes = [multiprocessing.Process(target=worker, args=(counter,)) for _ in range(10)]# 启动所有进程
for process in processes:process.start()# 等待所有进程完成
for process in processes:process.join()print(f"Counter value: {counter.value}")

GIL与并发编程

        全局解释器锁(GIL)是CPython解释器的一个机制,它确保同一时间只有一个线程执行Python字节码。这意味着即使在多线程程序中,CPU密集型任务也无法并行执行,从而限制了多线程的性能。

        GIL的存在主要是为了简化CPython解释器的内存管理,避免多线程同时访问共享内存时的竞态条件。但GIL对于I/O密集型任务影响较小,因为线程在等待I/O操作时可以释放GIL,让其他线程继续执行。

        为了提高CPU密集型任务的并发性,开发者通常采用多进程编程,因为每个进程都有自己的独立内存空间和GIL,不会受到限制。

多线程的优点与缺点

优点:

  • 线程创建和切换的开销较小;
  • 适合I/O密集型任务;
  • 线程共享内存空间,数据共享较为方便。

缺点:

  • 受GIL限制,CPU密集型任务无法并行执行;
  • 线程间共享数据需要同步,增加了编程复杂性。

多进程的优点与缺点

优点:

  • 每个进程都有独立内存空间,不受GIL限制;
  • 适合CPU密集型任务;
  • 进程间隔离性好,避免了数据竞争问题。

缺点:

  • 进程创建和切换的开销较大;
  • 进程间通信(IPC)相对复杂。

总结

        多线程和多进程是实现并发编程的重要手段,各有其适用场景和优缺点。在Python中,‘threading’ 模块适用于I/O密集型任务,而 ‘multiprocessing’ 模块则更适合CPU密集型任务。理解并灵活运用这些技术可以大幅提升程序的性能和处理能力,满足各种复杂应用的需求。

        通过本文的介绍,相信已经对Python中的多线程与多进程有了较为全面的了解。在实际开发中,根据具体的应用场景选择合适的并发方式,合理地利用线程和进程的优势,才能编写出高效、可靠的并发程序。

下一篇:白骑士的Python教学高级篇 3.2 网络编程​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/39440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据集成面试题

Flume 一、flume组成 --Agent Flume的部署单元,本质上是一个JVM进程,Agent主要由Source、Channel、Sink三个部分组成 --Source 收集数据,以event为单元进行封装发送给channel 参数配置:当采集速度比较慢,调整batchSize参数&…

IOS Swift 从入门到精通:写入 Firestore数据库

文章目录 FirestoreManager 类创建文档更新文档更新 Firestore 权限规则现在,我们想要在 Firestore 中添加或更新文档。如果您还没有,我建议您阅读有关设置 Firebase Auth 和从 Firestore 读取的部分。您必须在应用程序中启用 Firebase,并在项目中启用 Firestore 数据库,才…

【IT专业入门,高考假期预习指南】高考后的IT征途:启航前的准备与策略

IT专业入门,高考假期预习指南 七月来临,各省高考分数已揭榜完成。而高考的完结并不意味着学习的结束,而是新旅程的开始。对于有志于踏入IT领域的高考少年们,这个假期是开启探索IT世界的绝佳时机。作为该领域的前行者和经验前辈&a…

Java中的分布式事务管理

Java中的分布式事务管理 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Java中的分布式事务管理,这是在现代大规模应用中必须解决…

【SkiaSharp绘图14】SKCanvas方法详解(三)URL注释、按顶点绘制、 是否裁切区域之外、旋转、缩放、倾斜、平移、保存/恢复画布

文章目录 SKCanvas方法DrawUrlAnnotation 绘制URL注释DrawVertices 按顶点绘制Flush 立即绘制QuickReject 判断区域是否在裁切区域之外ResetMatrix重置矩阵Restore、RestoreToCountRotateDegrees按角度旋转画布RotateRadians按弧度旋转画布SaveLayer保存并新建图层Scale 缩放画…

Python协作运动机器人刚体力学解耦模型

🎯要点 🎯腿式或固定式机器人模型 | 🎯网格、点云和体素网格碰撞检测 | 🎯正反向运动学和动力学 | 🎯机器人刚体力学计算 | 🎯编辑参考系姿势和路径 | 🎯软件接口实体机器人模拟 | &#x1f3a…

使用shell脚本进行clang-tidy静态代码分析

文章目录 0. 引言1. 完整检测脚本代码 clang-tidy-check.sh1.1 流程图1.2 脚本功能概述 2. 该脚本优缺点 0. 引言 clang-tidy 是基于 Clang 的工具,提供了丰富的代码检查功能,可以根据用户配置文件进行定制化的检查和规则定义。 之前的文章《使用 Clang…

分子AI预测赛Task2笔记

下面所述比较官方的内容都来自官方文档 ‍‌⁠‌‍​​​‌​​⁠​​​​​​​​‍‬​​‍⁠‍‍​​‬​‌​​​‌‍‬​​​​​​‍‌Task2:赛题深入解析 - 飞书云文档 (feishu.cn) 赛题背景 强调了人工智能在科研领域&…

WebDriver API

WebDriver API 是一组允许程序控制和自动化Web浏览器的接口,它是Selenium框架的一部分。Selenium 是一个广泛使用的开源自动化测试工具,用于Web应用程序的自动化测试。WebDriver API 提供了与浏览器进行交互的能力,支持多种浏览器&#xff0c…

苹果电脑废纸篓数据被清空了,有什么方法可以恢复吗?

使用电脑的用户都知道,被删除的文件一般都会经过回收站,想要恢复它直接点击“还原”就可以恢复到原始位置。mac电脑同理也是这样,但是“回收站”在mac电脑显示为“废纸篓”。 苹果电脑废纸篓数据被清空了,有什么方法可以恢复吗&am…

java反射和注解

反射 获取class对象的三种方法 ①:Class.forName("全类名"); ②:类名.class ③:对象.getclass(); 代码样例 package com.ithema;public class Main {public static void main(String[] args) throws ClassNotFoundException {//第…

基于Canvas的Html5多时区动态时钟实战

目录 前言 一、关于Canvas技术 1、Canvas是什么 2、Canvas的属性及渲染特性 二、Canvas动态多时区展示 1、新建html页面 2、创建Canvas对象 3、绘制所有的时钟 总结 前言 出差旅行相信大家一定会住酒店,大家在酒店的前台进行预订的时候,是不是都…

centos执行yum相关命令报错的可能原因

文章目录 1. 执行yum命令是报下面一大帕拉2. 安装某个包报错,找不到这个包 1. 执行yum命令是报下面一大帕拉 最后一行报错,在repo文件中找不到空baseurl:xxx / x86_64 执行这行命令把这个找不到的 xxx 禁掉即可sudo yum-config-manager --di…

【项目日记(三)】搜索引擎-搜索模块

❣博主主页: 33的博客❣ ▶️文章专栏分类:项目日记◀️ 🚚我的代码仓库: 33的代码仓库🚚 🫵🫵🫵关注我带你了解更多项目内容 目录 1.前言2.项目回顾3.搜索流程3.1分词3.2触发3.3去重3.4排序3.5包装 4.总结 1.前言 在前…

Qt的源码目录集合(V5.12.12版本)

目录 1.QObject实现源码 2.qml中的ListModel实现源码 3.qml中的JS运行时的环境和数据类型源码 1.QObject实现源码 .\Qt\Qt5.12.12\5.12.12\Src\qtbase\src\corelib\kernel\qobject.h .\Qt\Qt5.12.12\5.12.12\Src\qtbase\src\corelib\kernel\qobject.cpp .\Qt\Qt5.12.12\5…

虚拟机USB——解决每次插U盘都得选择连接到主机还是虚拟机问题

虚拟机USB——解决每次插U盘都得选择连接到主机还是虚拟机问题 1.编辑–>首选项–> 2.如果想每次插U盘都连接到主机就选“将设备连接到主机” 如果想每次插U盘都进行选择,就选择“询问要执行的操作”

Vscode常用快捷键

前言: 使用环境:ubuntu22.04 按键组合功能AltO切换源/头文件CtrlK,CtrlC注释CtrlK,CtrlU取消注释CtrlK,CtrlI格式化F12跳转函数定义CtrlAlt-跳转函数后返回CtrlW关闭当前标签页CtrlB关闭右侧边栏Ctrl← /→光标移至单词首/尾CtrlShift←/→跳选单词选中CtrlDelete删…

【软考论文】论基于架构的软件设计方法及应用(ABSD)

目录 一、题目二、论文2.1 摘要2.2 正文三、扩展一、题目 基于架构的软件设计(Architecture-Based Software Design,ABSD)方法以构成软件架构的 商业、质量和功能需求 等要素来驱动整个软件的开发过程。ABSD是一个自顶向下,递归细化的软件开发方法,它以软件系统功能的分解…

GCP FrontendConfig 详解:优化您的云负载均衡

目录 1. 什么是GCP FrontendConfig? 2. FrontendConfig的主要功能 2.1 协议选择 2.2 SSL/TLS配置 2.3 重定向配置 2.4 自定义响应头 3. 配置FrontendConfig 4. FrontendConfig的高级特性 4.1 智能路由 4.2 流量控制 4.3 日志和监控 5. FrontendConfig最佳实践 5.…

Ubuntu22.04使用/etc/rc.local开机启动程序

前言 因为在工作中,Ubuntu系统经常使用到开机启动,为了方便之后使用,特此介绍下如何使用/etc/rc.local来开机启动程序,步骤如下,针对Ubuntu20.04或Ubuntu22.04系统都有效。 使用root权限编辑/lib/systemd/system/rc-…