当前位置: 首页 > article >正文

Python30_线程详解

Python30_线程详解文章目录Python30_线程详解[toc]一、进程和线程1. GIL锁2. 线程开发3. 线程安全4. 线程锁5. 死锁6. 线程池7. 线程和进程对比7.1 关系对比7.2 区别对比7.3 优缺点对比一、进程和线程先来了解一下进程和线程类比一个工厂至少有一个车间一个车间中至少有一个工人最终是工人在工作。一个程序至少有一个进程一个进程中至少有一个线程最终是线程在工作。上述串行的代码示例就是一个程序在使用python xx.py 运行时内部就创建了一个进程主进程在进程中创建了一个线程主线程由线程逐行运行代码。 线程是计算机中可以被cpu调度的最小单元 进程是计算机资源分配的最小单元进程为线程提供资源 一个进程中可以有多个线程同一个进程中的线程可以共享此进程中的资源。在Python中多线程和多进程是用来实现并发执行的两种机制。这些系统调用fork、spawn是底层操作系统提供的方式可以用来创建新的进程或者线程。1、 linux 系统fork在Linux系统中fork是一种创建进程的方式它会复制当前进程的状态创建一个新的进程。新的进程称为子进程而原始进程称为父进程。fork系统调用返回两次一次在父进程中返回子进程的PID一次在子进程中返回0。子进程会继承父进程的代码段、数据段、堆栈等信息。2、window系统spawn在Windows系统中spawn是一种创建进程的方式它通过调用CreateProcess函数来创建一个新的进程。与fork不同spawn在Windows系统中不能直接复制当前进程的状态而是需要指定要执行的程序路径。CreateProcess函数会创建一个新的进程并且可以指定该进程的参数、环境变量等信息。3、mac系统fork和spawn python3.8 默认支持spawn要是需要修改fork: multiprocessing.set_start_method(‘fork’)在Mac系统中fork和spawn两种方式都可以用来创建进程。fork与Linux中的fork类似复制当前进程的状态创建新的进程。而spawn与Windows中的spawn类似通过调用posix_spawn函数创建新的进程。对于Python的多线程和多进程可以使用threading和multiprocessing模块来实现。threading模块提供了线程相关的功能可以创建和管理线程。multiprocessing模块则提供了多进程相关的功能可以创建和管理进程。因此无论是在Linux、Windows还是Mac系统中都可以使用fork或spawn来创建新的进程并结合Python的多线程或多进程机制来实现并发执行的效果。具体选择哪种方式取决于所使用的操作系统和需求。1. GIL锁全局解释器锁( Global Interpreter Lock),是 CPython 解释器的功能让一个进程中同一时刻只能有一个线程可以被CPU调用。如果程序想利用计算机多核优势让CPU同时处理一些任务适合用多进程开发即使资源开销大。如果程序不利用计算机的多核优势适合用多线程开发常见的程序开发中计算操作需要使用CPU多核优势IO操作不需要利用多核优势所以就有一句话计算密集型用多进程例如大量的数据计算【累加计算实例】。IO密集型用多线程例如文件读写网络数据传输【下载抖音视频实例爬虫】。2. 线程开发线程的常见方法t.start()当前线程准备就绪等待CPU调度具体时间是由CPU来决定。t.join()等待当前线程的任务执行完毕后再向下继续执行。主线程等待子线程执行完毕在继续向下执行。t.setDaemon布尔值守护线程必须放在start之前t.setDaemon(True),设置为守护线程主线程执行完毕后子线程也自动关闭。t.setDaemon(False),设置为非守护线程主线程等待子线程子线程执行完毕后主线程才结束。默认线程名称的设置和获取 设置名字在start之前【注意事项线程的执行并不是按照顺序进行执行的】importthreadingdeftask(srd):# 获取当前执行此代码的线程# name threading.current_thread().getName()namethreading.current_thread().nameprint(f线程name:{name}- 参数:{srd})foriinrange(10):tthreading.Thread(targettask,args(i,))# 设置名字# t.setName(日魔-{}.format(i))t.name日魔-{}.format(i)t.start()打印结果线程name:日魔-0 - 参数:0 线程name:日魔-2 - 参数:2 线程name:日魔-3 - 参数:3 线程name:日魔-1 - 参数:1 线程name:日魔-4 - 参数:4 线程name:日魔-5 - 参数:5 线程name:日魔-6 - 参数:6 线程name:日魔-7 - 参数:7 线程name:日魔-8 - 参数:8 线程name:日魔-9 - 参数:9自定义线程类直接将线程需要做的是写到run方法中。importtimeimportrequestsimportthreadingclassDouYinThread(threading.Thread):defrun(self)file_name,video_urlself.args resrequests.get(video_url)withopen(file_name,modewb)asf:f.write(res.content)url_list[(东北F4模仿秀.mp4,https://aweme.snssdk.com/aweme/v1/playwm/?video_idv0300f570000bvbmace0gvch7lo53oog),(卡特扣篮.mp4,https://aweme.snssdk.com/aweme/v1/playwm/?video_idv0200f3e0000bv52fpn5t6p007e34q1g),(罗斯mvp.mp4,https://aweme.snssdk.com/aweme/v1/playwm/?video_idv0200f240000buuer5aa4tij4gv6ajgg)]forname,urlinurl_list:tDouYinThread(args(name,url))t.start()3. 线程安全importthreading lock_objectthreading.RLock()loop10000000number0def_add(count):lock_object.acquire()# 加锁申请锁没申请到则等待globalnumberforiinrange(count):number1lock_object.release()# 释放锁def_sub(count):lock_object.acquire()globalnumberforiinrange(count):number-1lock_object.release()tthreading.Thread(target_add,args(loop,))t1threading.Thread(target_sub,args(loop,))t.start()t1.start()t.join()t1.join()print(number)使用 with关键字加锁importthreading num0lock_objectthreading.RLock()# def task():# print(开始)# lock_object.acquire()# global num# for i in range(1000000):# num 1# lock_object.release()# print(num)# for i in range(2):# t threading.Thread(targettask)# t.start()deftask1():print(开始)withlock_object:globalnumforiinrange(1000000):num1print(num)foriinrange(2):tthreading.Thread(targettask1)t.start()对于有些数据是安全的数据类型不需要加锁list.append(x)list.extend(l2)x list[i]x pop()list[i:j] list2list.sort()x yx.feadf ydict[x] ydict1.update(dict2)dict.keys()不安全的数据类型操i 1list1[i] list1[j]dict[x] dict[x]14. 线程锁在程序中如果想要自己手动加锁一般有两种Lock和RLock。Lock 同步锁不支持锁的嵌套比较RLockLock的效率更高性能更好RLock 递归锁 支持锁的嵌套应用场景比较多比如你写了一个函数用到锁了然后你同事也写了一个函数也遇到锁了并调用你的函数时就遇到嵌套锁所以遇到这种嵌套的就要用RLock5. 死锁多线程和进程的死锁是并发编程中常见的问题它们指的是在多个线程或进程中相互等待对方释放资源而无法继续执行的情况。多线程死锁 多线程死锁指的是两个或多个线程因为争夺资源而相互等待导致程序无法继续执行下去。通常出现死锁的情况需要满足以下四个条件互斥、占有且等待、不可抢占和循环等待。 示例代码如下import threading # 创建资源对象 resourceA threading.Lock() resourceB threading.Lock() # 线程1获取资源A后尝试获取资源B def thread1(): resourceA.acquire() resourceB.acquire() # 执行操作... resourceB.release() resourceA.release() # 线程2获取资源B后尝试获取资源A def thread2(): resourceB.acquire() resourceA.acquire() # 执行操作... resourceA.release() resourceB.release() # 创建线程并启动 t1 threading.Thread(targetthread1) t2 threading.Thread(targetthread2) t1.start() t2.start()在上述代码中线程1先获取了资源A然后尝试获取资源B而线程2先获取了资源B然后尝试获取资源A。由于两个线程相互等待对方释放资源导致了死锁的发生。进程死锁 进程死锁与多线程死锁类似只不过是在并发执行的多个进程 ** 现相互等待的情况。进程死锁的解决方法通常通过资源分配顺序的调整、加锁的合理释放、避免持有多个锁等方式来避免。示例代码如下import multiprocessing # 创建资源对象 resourceA multiprocessing.Lock() resourceB multiprocessing.Lock() # 进程1获取资源A后尝试获取资源B def process1(): resourceA.acquire() resourceB.acquire() # 执行操作... resourceB.release() resourceA.release() # 进程2获取资源B后尝试获取资源A def process2(): resourceB.acquire() resourceA.acquire() # 执行操作... resourceA.release() resourceB.release() # 创建进程并启动 p1 multiprocessing.Process(targetprocess1) p2 multiprocessing.Process(targetprocess2) p1.start() p2.start()在上述代码中进程1先获取了资源A然后尝试获取资源B而进程2先获取了资源B然后尝试获取资源A。同样地由于两个进程相互等待对方释放资源导致了死锁的发生。6. 线程池线程不是开的越多越好开的多了可能会导致系统的性能更低了所以就引入线程池importtimefromconcurrent.futuresimportThreadPoolExecutordeftask(video_url):print(开始执行任务,video_url)time.sleep(5)# 创建线程池最多维护10个线程poolThreadPoolExecutor(10)url_list[www.xxxx-{}.com.format(i)foriinrange(300)]forurlinurl_list:# 在线程池中提交一个任务线程池中如果有空闲的线程侧立马分配空前的线程去执行执行完毕后再将线程交还给线程池如果没有空闲的线程则等待pool.submit(task,url)print(start)pool.shutdown(True)# 等待线程池中的任务执行完毕后在继续执行有点像线程的join方法print(end)线程池任务完成可以干些别的事情比如执行完成后再让他做写其他事情比如爬取数据后执行完后再将其写入一个文件中多任务importtimefromconcurrent.futuresimportThreadPoolExecutordeftask(video_url):print(开始执行任务,video_url)time.sleep(5)defdone(response):print(任务执行后的返回值)# 创建线程池最多维护10个线程poolThreadPoolExecutor(10)url_list[www.xxxx-{}.com.format(i)foriinrange(15)]forurlinurl_list:# 在线程池中提交一个任务线程池中如果有空闲的线程侧立马分配空前的线程去执行执行完毕后再将线程交还给线程池如果没有空闲的线程则等待futurespool.submit(task,url)futures.add_done_callback(done)# 时子主线程执行print(start)pool.shutdown(True)# 等待线程池中的任务执行完毕后在继续执行有点像线程的join方法print(end)# 可以分工, 例如:task函数专门下载, Done函数 专门将下载的数据写入本地文件中7. 线程和进程对比7.1 关系对比线程式依附在进程里面的没有进程就没有线程。一个进程默认提供一个线程一个进程可以创建多个线程7.2 区别对比创建进程的资源开销要比创建线程开销要大因为创建一个进程里面默认有一个线程进程是操作系统资源分配的基本单位线程是cpu调度的基本单位线程不能独立执行必须依附存在进程中7.3 优缺点对比进程优点可以使用多核缺点资源开销大线程优点开销小缺点不能使用多核

相关文章:

Python30_线程详解

Python30_线程详解 文章目录Python30_线程详解[toc]一、进程和线程1. GIL锁2. 线程开发3. 线程安全4. 线程锁5. 死锁6. 线程池7. 线程和进程对比7.1 关系对比7.2 区别对比7.3 优缺点对比一、进程和线程 先来了解一下进程和线程 类比: 一个工厂,至少有…...

别再让内存拖后腿:图解PCIe No Snoop与Intel DDIO如何为你的高速网卡加速

突破内存瓶颈:PCIe No Snoop与Intel DDIO技术在高性能网络中的实战指南 当100GbE网卡的实际吞吐量始终无法突破60%利用率时,大多数工程师的第一反应往往是检查网卡配置或驱动版本。但真正的问题可能隐藏在CPU与内存之间那条看不见的数据高速公路上——传…...

开发者心理健康防御系统构建:软件测试从业者的专业防线

在数字化转型的洪流中,软件测试工程师作为产品质量的终极守门人,长期处于一个“高压-高责任-低可见性”的独特困境。技术迭代的飞速步伐、需求的频繁变更、线上事故的归责压力,交织成一张无形却沉重的网,使测试从业者成为心理耗损…...

Python29_并发编程

Python29_并发编程 文章目录Python29_并发编程[toc]基本概念1 并发 vs 并行2 Python 的并发模型多线程编程1 基本使用2 线程同步3 线程间通信多进程编程1 基本使用2 进程池3 进程间通信异步IO(asyncio)1 基本概念2 基本使用3 高级特性并发编程选择指南实际应用示例1 并发下载器…...

开源项目管理软件OpenProject:团队协作的终极免费解决方案

开源项目管理软件OpenProject:团队协作的终极免费解决方案 【免费下载链接】openproject OpenProject is the leading open source project management software. 项目地址: https://gitcode.com/GitHub_Trending/op/openproject 还在为团队协作效率低下而烦…...

LinkSwift:八大网盘直链下载助手,告别限速烦恼的终极解决方案

LinkSwift:八大网盘直链下载助手,告别限速烦恼的终极解决方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中…...

AI_产品经理|一文读懂大模型到底是怎么工作的

Part 1|大模型为什么给人一种"无所不知"的错觉 很多人第一次用 ChatGPT 或 Claude 时的本能反应是:它怎么什么都知道? 答案其实没那么玄乎。 大模型和搜索引擎一样,干了同一件苦力活:看过了互联网上几乎所有…...

告别数据孤岛!知识图谱:驱动企业智能决策的“大脑”引擎

专注于 知识图谱构建与应用开发,提供一站式定制化服务,帮助企业和科研机构高效管理知识资源、挖掘隐性关系、实现智能决策。服务内容包括: 知识图谱构建:从数据采集、实体抽取、关系识别到图谱建模,全流程专业处理&am…...

2026最新突破,Transformer架构升级、GLM-5深度解析,效率与成本平衡大揭秘!

引言 2026年,大模型技术迎来了前所未有的发展浪潮。从 GLM-5 到最新的 Transformer 变体,技术边界不断被突破。本文将深入分析当前大模型领域的关键技术进展。 一、Transformer 架构的演进 1.1 位置编码的新突破 传统 Transformer 使用固定的位置编码&am…...

微软借助环境感知服务网络简化 AKS 服务网格管理,开启新功能指南来了!

微软借助环境感知服务网络简化 AKS 服务网格扩展与管理微软借助基于环境感知(ambient)的服务网络,简化了 Azure Kubernetes 服务(AKS)的服务网格扩展和管理。以下是如何开启这一功能。如果你正在使用 Kubernetes&#…...

RTX3050笔记本跑TensorFlow-GPU?保姆级避坑指南(Win11 + CUDA 11.5 + cuDNN 8.3.3)

RTX3050笔记本TensorFlow-GPU实战:Win11环境下的精准配置与性能调优 1. 笔记本GPU环境配置的特殊挑战 RTX3050笔记本在深度学习应用中面临着一系列独特挑战。与台式机不同,笔记本的集成显卡设计、功耗限制和散热问题常常成为配置过程中的隐形杀手。许多用…...

8大主流网盘直链下载工具LinkSwift:架构解析与技术实现深度剖析

8大主流网盘直链下载工具LinkSwift:架构解析与技术实现深度剖析 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云…...

Source Han Serif CN开源中文字体:企业级字体解决方案的技术实现与应用实践

Source Han Serif CN开源中文字体:企业级字体解决方案的技术实现与应用实践 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 在数字内容创作和商业设计领域,中文…...

Python实战:基于Hessian矩阵的Steger激光条纹中心提取算法

1. 激光条纹中心提取的工业应用场景 在工业质检领域,激光三角测量技术被广泛应用于物体表面形貌检测。当激光器投射到物体表面时,会形成一条明亮的激光条纹。这条条纹的形变程度反映了物体表面的高度变化,而要精确计算这些形变,首…...

NLP 注意力机制:从Transformer到GPT

NLP 注意力机制:从Transformer到GPT 1. 引言 注意力机制(Attention Mechanism)已成为现代自然语言处理(NLP)的核心技术,从Transformer架构的提出到GPT系列模型的演进,注意力机制的应用和改进推动…...

RabbitMQ 核心角色:什么是生产者和消费者?全流程图解+实战详解

RabbitMQ 核心角色:什么是生产者和消费者?全流程图解实战详解前言一、核心概念定义:什么是 RabbitMQ 生产者和消费者?1.1 生产者(Producer):定义与作用1.2 消费者(Consumer&#xff…...

PyTorch 分布式训练:DDP vs FSDP

PyTorch 分布式训练:DDP vs FSDP 核心结论 DDP (DistributedDataParallel):基于数据并行的分布式训练方法,适用于中小规模模型FSDP (FullyShardedDataParallel):基于模型分片的分布式训练方法,适用于超大规模模型性能对…...

RabbitMQ 实战指南:如何声明队列?队列声明必要参数与完整用法详解

RabbitMQ 实战指南:如何声明队列?队列声明必要参数与完整用法详解前言一、队列声明认知:什么是队列声明?为什么要声明?1.1 定义1.2 核心作用1.3 队列声明流程图二、队列声明基础语法:如何声明一个队列&…...

消息中间件实战:RabbitMQ基本架构与核心组件全解析

消息中间件实战:RabbitMQ基本架构与核心组件全解析前言一、RabbitMQ 架构认知:RabbitMQ 基本架构是什么?1.1 架构定义1.2 整体架构流程图1.3 架构核心特点二、RabbitMQ 核心组件:RabbitMQ 包含哪些核心组件?2.1 组件一…...

BUAA编译原理核心考点实战解析:从随堂测试到知识脉络

1. 从零散题目到知识图谱:编译原理学习新视角 第一次翻开编译原理课本时,相信很多同学和我一样,面对词法分析、语法分析、语义分析这些概念一头雾水。更让人头疼的是,随堂测试里的题目看似简单,却总能在细节处挖坑无数…...

实战Windbg:从线上死锁到内存异常的全链路调试指南

1. 初识Windbg:调试利器与线上救火场景 第一次接触Windbg是在一个深夜的线上告警中。当时我们的订单处理服务突然卡死,监控显示线程数暴涨但CPU利用率却很低,典型的死锁特征。由于是生产环境,既不能随意重启服务,又无法…...

从实验室到日常生活:马吕斯定律在LCD屏幕和太阳镜中的神奇应用

偏振光的魔法:马吕斯定律如何塑造现代科技产品 清晨的阳光透过窗帘缝隙洒进房间,你伸手摸到床头的手机,屏幕瞬间亮起——这个再普通不过的动作背后,隐藏着一个200多年前发现的物理定律。当我们戴上太阳镜在户外活动,或…...

Livox Avia面阵激光雷达深度解析:双扫描模式如何重塑行业应用边界

1. Livox Avia面阵激光雷达的核心突破:双扫描模式解析 第一次拿到Livox Avia时,最让我惊讶的是它不到500克的机身里竟藏着两种完全不同的扫描模式。这就像一台相机同时拥有广角镜头和长焦镜头——非重复扫描模式如同广角镜头,能瞬间捕捉70.47…...

从指示灯到指令:全面解析仿真器连接与调试实战要点

1. 仿真器连接前的硬件准备 第一次拿到仿真器时,很多新手开发者会迫不及待地直接连接目标板开始调试,这种做法往往会导致各种连接问题。根据我多年的嵌入式开发经验,正确的做法是先做好充分的硬件准备工作。 首先需要检查仿真器的接口类型。目…...

终极指南:OpenIPC固件在君正T31平台烧录疑难问题完全解决方案

终极指南:OpenIPC固件在君正T31平台烧录疑难问题完全解决方案 【免费下载链接】firmware Alternative IP Camera firmware from an open community 项目地址: https://gitcode.com/gh_mirrors/fir/firmware OpenIPC是一款基于Buildroot的开源IP摄像头固件项目…...

从零开始:Nuclei工具的快速安装与配置指南

1. 为什么选择Nuclei进行漏洞扫描 第一次接触Nuclei是在去年的一次内部安全审计中。当时我们需要在短时间内对上百个Web服务进行漏洞检测,传统的手动测试方式显然不现实。同事推荐了这款开源工具,用他的话说就是"像瑞士军刀一样全能"。实际使用…...

如何轻松实现Zotero中文文献自动化管理:Jasminum插件的完整实践指南

如何轻松实现Zotero中文文献自动化管理:Jasminum插件的完整实践指南 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件,用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 还…...

CANoe回灌报文信号值修改实战:用CAPL脚本动态调整Replay模块回放数据(附完整代码)

CANoe回灌报文信号值动态修改实战指南:CAPL脚本深度解析与代码优化 在汽车电子测试领域,回灌测试(Replay Test)是验证控制器逻辑的重要手段。但实际工作中,工程师常遇到这样的困境:精心录制的BLF文件中的某…...

从Cortex-M3到RTOS:构建嵌入式开发的核心知识图谱

1. Cortex-M3内核的底层奥秘 第一次接触Cortex-M3内核时,我被它精巧的设计震撼到了。这个只有拇指大小的芯片里,竟然藏着如此复杂的运行机制。就像打开一个精密的瑞士手表,每个齿轮都严丝合缝地配合着。Cortex-M3采用哈佛架构,这意…...

高效论文降重方案:2026年TOP5平台极限横评,AIGC疑似率实测降至5%!

【博主避坑指南】 CSDN的科研人们,5月定稿季到了,你的论文过审了吗?最近我每天收到的私信全在哀嚎:“老学长,我为了降重用了某某大模型改写,查重率倒是降到7%了,但教务处新上的‘知网AIGC检测V5…...