大唐面试-国企
1、数据结构知识汇总
1.1 python的数据类型
当然可以!以下是一个完整的关于 Python 数据类型“可变与不可变”的对比表格,清晰明了地展示了常见类型的分类与特性:
🧾 Python 数据类型:可变 vs 不可变
| 类别 | 数据类型 | 示例 | 是否可变 | 修改后对象 id 是否变化 | 
说明 | 
|---|---|---|---|---|---|
| 不可变类型 | int | 
x = 10 | 
否 | 是 | 数值变化生成新对象 | 
| 不可变类型 | float | 
x = 3.14 | 
否 | 是 | 浮点数变化生成新对象 | 
| 不可变类型 | str | 
s = "hello" | 
否 | 是 | 字符串内容变动会生成新字符串对象 | 
| 不可变类型 | tuple | 
t = (1, 2, 3) | 
否 | 是 | 元组不可增删改 | 
| 不可变类型 | bool | 
flag = True | 
否 | 是 | True/False 为常量 | 
| 不可变类型 | frozenset | 
fs = frozenset([1, 2]) | 
否 | 是 | 冻结集合,不能添加元素 | 
| 可变类型 | list | 
lst = [1, 2, 3] | 
是 | 否 | 添加/删除元素不改变对象本身 | 
| 可变类型 | dict | 
d = {"a": 1} | 
是 | 否 | 可以增删键值对 | 
| 可变类型 | set | 
s = {1, 2, 3} | 
是 | 否 | 可以添加/删除元素 | 
| 可变类型 | 自定义对象 | class MyClass: pass | 
是 | 否 | 属性可变 | 
- 不可变类型的值在对象创建之后不能被修改,任何对该对象的修改都会生成一个新的对象。
- 不可变类型作为参数传入函数时,函数内部修改不会影响原对象。
 
 - 可变类型的值在对象创建之后可以修改,修改不会改变对象的 id。
- 可变类型作为参数传入函数时,函数内部修改会影响原对象。
 
 
1.2 深浅拷贝
你的代码有一些问题,我来解释并修正:
print(c.append(10))和print(d.append(10))会打印None,因为list.append()方法返回None- 你创建了两个独立的对象 
a和b,这不是展示拷贝效果的好方式 
代码及解释
import copy
# 原始列表(包含嵌套的可变对象)
original = [1, 2, [1, 2, 2], 8, 9]
# 浅拷贝
shallow_copy = copy.copy(original)
# 深拷贝
deep_copy = copy.deepcopy(original)
# 修改拷贝后的列表
shallow_copy.append(10)  # 添加元素到浅拷贝
deep_copy.append(10)     # 添加元素到深拷贝
print("原始列表:", original)         # [1, 2, [1, 2, 2], 8, 9]
print("浅拷贝:", shallow_copy)      # [1, 2, [1, 2, 2], 8, 9, 10]
print("深拷贝:", deep_copy)         # [1, 2, [1, 2, 2], 8, 9, 10]
# 现在修改嵌套列表来展示关键区别
shallow_copy[2].append(3)  # 会影响原始列表
deep_copy[2].append(3)     # 不会影响原始列表
print("\n修改嵌套列表后:")
print("原始列表:", original)         # [1, 2, [1, 2, 2, 3], 8, 9] ← 被浅拷贝修改影响了
print("浅拷贝:", shallow_copy)      # [1, 2, [1, 2, 2, 3], 8, 9, 10]
print("深拷贝:", deep_copy)         # [1, 2, [1, 2, 2, 3], 8, 9, 10]
关键点说明
- 
浅拷贝 (
copy.copy()):- 创建了新列表对象
 - 但内部的嵌套列表仍然是原始列表的引用
 - 修改嵌套列表会影响原始列表
 
 - 
深拷贝 (
copy.deepcopy()):- 完全递归复制了整个对象结构
 - 创建了全新的嵌套列表对象
 - 修改不会影响原始列表
 
 - 
-对于不可变类型(如元组、字符串),深浅拷贝几乎没有实际区别
 
1.3 Python中的可迭代类型
可迭代类型是Python中非常重要的概念,它是指能够一次返回一个元素的对象。以下是关于Python可迭代类型的详细说明:
什么是可迭代对象?
可迭代对象(Iterable)是指实现了__iter__()方法的对象,或者实现了__getitem__()方法且可以从0开始索引的对象。可迭代对象可以被用于for循环、解包等操作。
常见的可迭代类型
1. 基础可迭代类型
- 
序列类型:
- 列表(
list):[1, 2, 3] - 元组(
tuple):(1, 2, 3) - 字符串(
str):"hello" - 范围(
range):range(5) 
 - 列表(
 - 
集合类型:
- 集合(
set):{1, 2, 3} - 冻结集合(
frozenset):frozenset([1, 2, 3]) 
 - 集合(
 - 
映射类型:
- 字典(
dict):{"a": 1, "b": 2}(迭代键) 
 - 字典(
 
2. 高级可迭代类型
- 
生成器(
generator):(x for x in range(5)) # 生成器表达式 - 
文件对象:
with open('file.txt') as f: # f是可迭代的 for line in f: print(line) - 
自定义可迭代类:
class MyIterable: def __iter__(self): return iter([1, 2, 3]) 
如何判断对象是否可迭代?
- 
使用
collections.abc.Iterable:from collections.abc import Iterable isinstance([1, 2, 3], Iterable) # True isinstance(123, Iterable) # False - 
检查是否有
__iter__方法:hasattr([1, 2, 3], '__iter__') # True 
可迭代对象的特点
- 惰性求值:某些可迭代对象(如生成器)只在需要时计算值
 - 一次性使用:某些可迭代对象(如生成器、文件对象)只能迭代一次
 - 内存高效:不需要一次性加载所有数据到内存
 
可迭代对象 vs 迭代器
| 特性 | 可迭代对象 (Iterable) | 迭代器 (Iterator) | 
|---|---|---|
| 定义 | 实现了__iter__() | 
实现了__iter__()和__next__() | 
| 用途 | 可以用于for循环 | 
可以用于for循环,且可以手动调用next() | 
| 状态 | 无状态 | 有状态,记住迭代位置 | 
| 示例 | [1, 2, 3], range(5) | 
iter([1, 2, 3]), 生成器 | 
实际应用
- 
for循环:
for item in [1, 2, 3]: # 列表是可迭代的 print(item) - 
解包操作:
a, b, c = [1, 2, 3] # 列表解包 - 
内置函数:
list('hello') # ['h', 'e', 'l', 'l', 'o'] sum([1, 2, 3]) # 6 - 
生成器表达式:
squares = (x**2 for x in range(5)) # 惰性计算 
2、Python的优点
2.1 python的应用和常用的包
- 文件或者操作系统:os,pathlib
 - 数据与数学:math,random,datetime、statistics
 - 数据序列化与压缩:json.dumps({key,value}),zipfile,pickle.dumps
 - 网络与并发:requests.get(),socket-底层网络通讯,threading.Thread(target=func).start(),multiprocessing.Process(target=func).start()
 - 调试与测试:logging
 - 正则表达式:re
 - CSV文件:csv
 
2.1.1 Web开发:
- flask 轻量级Web框架 pip install flask 快速构建REST API
 - django 全功能Web框架(ORM、Admin) pip install django 企业级Web应用开发
 - requests HTTP请求库(人性化API) pip install requests 爬虫、调用第三方API
 - beautifulsoup4 HTML/XML解析(爬虫) pip install beautifulsoup4 网页数据抓取
 - fastapi 高性能API框架(异步支持) pip install fastapi 微服务后端开发
 
2.1.2 机器学习与AI:
- scikit-learn 机器学习算法(分类/回归/聚类) pip install scikit-learn 训练预测模型(如SVM、随机森林)
 - tensorflow 深度学习框架(Google开发) pip install tensorflow 神经网络、图像识别
 - pytorch 动态深度学习框架(Meta开发) pip install torch NLP、自定义模型训练
4.keras 高层神经网络API(简化TensorFlow) pip install keras 快速搭建深度学习模型
5.opencv-python 计算机视觉(图像处理) pip install opencv-python 人脸检测、视频分析 
2.1.3数据库与ORM:
- sqlalchemy 数据库ORM(支持多种数据库) pip install sqlalchemy Python对象映射到SQL表
 - pymysql MySQL连接驱动 pip install pymysql 操作MySQL数据库
 - redis Redis数据库客户端 pip install redis 缓存、消息队列
 - pymongo MongoDB官方驱动 pip install pymongo NoSQL文档存储
 
2.1.4 数据科学分析:
包名用途安装命令示例场景
- numpy 高性能数值计算(多维数组) pip install numpy 矩阵运算、线性代数
 - pandas 数据处理与分析(DataFrame) pip install pandas CSV清洗、时间序列分析
 - matplotlib 数据可视化(2D/3D绘图) pip install matplotlib 绘制折线图、柱状图
 - seaborn 统计可视化(基于matplotlib) pip install seaborn 热力图、分布图
 - scipy 科学计算(优化、信号处理) pip install scipy 傅里叶变换、数值积分
 
2.1.5自动化与运维:
- selenium 浏览器自动化(Web测试/爬虫) pip install selenium 模拟用户点击、表单提交
 - paramiko SSH协议库(远程操作服务器) pip install paramiko 批量执行Linux命令
 - psutil 系统监控(CPU/内存/磁盘) pip install psutil 服务器性能分析
 - fabric 自动化部署工具 pip install fabric 远程任务执行
 
2.2 Python相比其他语言的优势
以下是Python与Java、C、Go的对比表格,突出Python的主要优点:
| 特性 | Python | Java | C | Go | 
|---|---|---|---|---|
| 语法简洁性 | ✅ 代码简洁,接近自然语言,学习成本低 | ❗ 需要显式类型声明,代码冗长 | ❗ 语法复杂,手动内存管理 | ⚠️ 比Java/C简单,但不如Python灵活 | 
| 开发效率 | ✅ 动态类型,快速原型开发,适合敏捷 | ⚠️ 需编译,类型严格,开发周期较长 | ❗ 开发效率低,需处理底层细节 | ⚠️ 编译型,但语法简单,编译速度快 | 
| 性能 | ❗ 解释执行,速度较慢(但可用Cython优化) | ⚠️ JIT优化,性能中等 | ✅ 原生编译,性能最高 | ✅ 编译型,性能接近C,优于Python/Java | 
| 跨平台性 | ✅ 解释器跨平台,一次编写到处运行 | ✅ JVM跨平台 | ❗ 需重新编译适配不同平台 | ✅ 编译为二进制,跨平台支持好 | 
| 内存管理 | ✅ 自动垃圾回收 | ✅ 自动GC(但可能有STW问题) | ❗ 手动管理内存(易泄漏/溢出) | ✅ 自动GC,侧重轻量级并发 | 
| 并发模型 | ⚠️ GIL限制多线程,推荐多进程/协程(asyncio) | ✅ 多线程支持(但线程重量级) | ❗ 需手动管理线程/同步 | ✅ 原生goroutine,高并发轻量级 | 
| 标准库/生态 | ✅ 覆盖广泛(Web、AI、科学计算等) | ✅ 企业级库成熟(Spring/Hibernate等) | ❗ 标准库功能有限,依赖第三方 | ⚠️ 标准库实用,但生态较新(如Web框架较少) | 
| 动态特性 | ✅ 动态类型、元编程、反射支持灵活 | ⚠️ 静态类型,反射有限 | ❗ 无动态特性 | ❗ 静态类型,无继承/泛型支持弱 | 
| 适用领域 | 脚本、AI、数据分析、Web后端、自动化 | 企业应用、Android、大数据(Hadoop) | 操作系统、嵌入式、高性能计算 | 云原生、微服务、CLI工具、高并发后端 | 
| 典型应用 | Django、NumPy、TensorFlow | Spring、Hadoop、Android SDK | Linux内核、Redis、Nginx | Docker、Kubernetes、Prometheus | 
关键结论
- 选Python:追求开发效率、快速迭代、数据科学/AI。
 - 选Java/C/Go:需要高性能(C)、强类型安全(Java)、高并发(Go)。
✅ Python是动态类型 + 强类型语言,而非弱类型。 
2.3 以下是关于Python语言特性及其类型系统的详细说明:
一、Python的核心特性
| 特性 | 说明 | 
|---|---|
| 动态类型 | 变量无需声明类型,运行时自动推断(如 x = 10 后可改为 x = "str")。 | 
| 强类型 | 类型检查严格,不支持隐式类型转换(如 "10" + 1 会报错,需显式转换)。 | 
| 解释执行 | 代码逐行解释运行,无需编译(但生成字节码缓存)。 | 
| 自动内存管理 | 引用计数 + 垃圾回收(GC)机制,无需手动释放内存。 | 
| 多范式支持 | 支持面向对象(OOP)、函数式编程(如 map()、lambda)、过程式编程。 | 
| 丰富的标准库 | 内置模块覆盖文件I/O、网络、正则表达式等(如 os、json、re)。 | 
| 动态元编程 | 支持反射、装饰器、元类等运行时修改代码的行为。 | 
| 跨平台 | 通过解释器实现跨平台运行(Windows/Linux/macOS)。 | 
| 胶水语言 | 可轻松调用C/C++(通过Cython)、Java(JPype)、.NET(Python.NET)等代码。 | 
二、Python是弱类型语言吗?
1. 动态类型 vs 弱类型
- 动态类型:变量类型在运行时确定,且可随时改变(Python属于此类)。
x = 10 # x是整数 x = "hello" # x变为字符串 - 弱类型:允许隐式类型转换,类型规则宽松(如JavaScript、PHP)。
// JavaScript(弱类型) console.log("10" + 1); // 输出 "101"(字符串拼接)# Python(强类型) print("10" + 1) # 报错!需显式转换:print("10" + str(1)) 
2. Python的强类型表现
- 类型检查严格:不同类型操作需显式转换。
# 需手动转换类型 print(int("10") + 1) # 输出 11 print(str(10) + "abc") # 输出 "10abc" - 对比真正弱类型语言:
- C语言(弱类型):
printf("%d", "10");可能输出乱码(无类型检查)。 - PHP:
echo "10" + 1;直接输出11(自动转换)。 
 - C语言(弱类型):
 
结论:
✅ Python是动态类型 + 强类型语言,而非弱类型。
三、与其他语言的类型系统对比
| 语言 | 类型系统 | 示例行为 | 
|---|---|---|
| Python | 动态 + 强类型 | "10" + 1 → 报错(需显式转换) | 
| Java | 静态 + 强类型 | String x = 10; → 编译报错 | 
| C | 静态 + 弱类型 | int x = "10"; → 编译警告(可能运行) | 
| Go | 静态 + 强类型 | x := "10" + 1 → 编译报错 | 
| JavaScript | 动态 + 弱类型 | "10" + 1 → "101"(自动转换) | 
四、Python类型系统的优缺点
优点
- 灵活性高:快速开发时无需纠结类型声明。
 - 代码简洁:减少类型相关的样板代码。
 - 适合原型设计:轻松调整变量用途。
 
总结
- Python特性:动态类型、强类型、解释型、多范式、自动内存管理。
 - 弱类型误区:Python不允许隐式类型转换,故不属于弱类型语言。
 - 适用场景:动态类型适合快速开发,强类型避免隐藏错误。
 
3、Flask 和 Django区别
(1)Flask
Flask确实很“轻”,不愧是Micro Framework,从Django转向Flask的开发者一定会如此感慨,除非二者均为深入使用过
Flask自由、灵活,可扩展性强,第三方库的选择面广,开发时可以结合自己最喜欢用的轮子,也能结合最流行最强大的Python库入门简单,即便没有多少web开发经验,也能很快做出网站
非常适用于小型网站
非常适用于开发web服务的API
开发大型网站无压力,但代码架构需要自己设计,开发成本取决于开发者的能力和经验
各方面性能均等于或优于Django
Django自带的或第三方的好评如潮的功能,Flask上总会找到与之类似第三方库
Flask灵活开发,Python高手基本都会喜欢Flask,但对Django却可能褒贬不一
Flask与关系型数据库的配合使用不弱于Django,而其与NoSQL数据库的配合远远优于Django
Flask比Django更加Pythonic,与Python的philosophy更加吻合
(2)Django
Django太重了,除了web框架,自带ORM和模板引擎,灵活和自由度不够高
Django能开发小应用,但总会有“杀鸡焉用牛刀”的感觉
Django的自带ORM非常优秀,综合评价略高于SQLAlchemy
Django自带的模板引擎简单好用,但其强大程度和综合评价略低于Jinja
Django自带ORM也使Django与关系型数据库耦合度过高,如果想使用MongoDB等NoSQL数据,需要选取合适的第三方库,且总感觉Django+SQL才是天生一对的搭配,Django+NoSQL砍掉了Django的半壁江山
Django目前支持Jinja等非官方模板引擎
Django自带的数据库管理app好评如潮
Django非常适合企业级网站的开发:快速、靠谱、稳定
Django成熟、稳定、完善,但相比于Flask,Django的整体生态相对封闭
Django是Python web框架的先驱,用户多,第三方库最丰富,最好的Python库,如果不能直接用到Django中,也一定能找到与之对应的移植
Django上手也比较容易,开发文档详细、完善,相关资料丰富
4、Python的进程、线程和协程
4.1 三者区别
| 特性 | 进程 (Process) | 线程 (Thread) | 协程 (Coroutine) | 
|---|---|---|---|
| 隔离性 | 完全隔离,独立内存空间 | 共享内存,需同步机制 | 共享内存,但通过协作式调度避免竞争 | 
| 创建开销 | 大(需复制资源) | 较小 | 极小(仅需保存上下文) | 
| 切换成本 | 高(需切换内存空间) | 中(需内核调度) | 极低(用户态切换) | 
| 并行性 | 真并行(多核CPU) | 受GIL限制(CPython中伪并行) | 单线程内并发 | 
| 通信方式 | 管道、队列、共享内存等IPC | 共享变量(需锁) | 直接共享变量(无锁) | 
| 适用场景 | CPU密集型任务、需要隔离的任务 | I/O密集型、需要共享状态的并发 | 高并发I/O操作、异步编程 | 
技术实现细节
1. 进程 (Process)
from multiprocessing import Process
def task():
    print("Process running")
p = Process(target=task)
p.start()
p.join()
- 优点:绕过GIL限制,利用多核CPU
 - 缺点:通信成本高,资源占用大
 
2. 线程 (Thread)
from threading import Thread
def task():
    print("Thread running")
t = Thread(target=task)
t.start()
t.join()
- 优点:共享内存方便,创建成本低
 - 缺点:受GIL限制,调试困难(竞态条件)
 
3. 协程 (Coroutine)
import asyncio
async def task():
    print("Coroutine running")
asyncio.run(task())
- 优点:超高并发能力,资源消耗极低
 - 缺点:需要异步编程范式,不能利用多核
 
选择决策树
- 
是否需要真并行(利用多核CPU)?
- 是 → 选择进程
 - 否 → 进入下一步
 
 - 
是否主要是I/O密集型任务?
- 是 → 进入下一步
 - 否(CPU密集型)→ 在Python中只能选择进程(因GIL限制)
 
 - 
是否需要超高并发(>1000连接)?
- 是 → 选择协程
 - 否 → 选择线程
 
 
典型应用场景
进程的最佳场景
- 数学计算(NumPy/Pandas运算)
 - 科学计算/机器学习训练
 - 需要强隔离的安全敏感任务
 - 长时间运行的独立后台服务
 
线程的最佳场景
- 网络请求(HTTP API调用)
 - 数据库操作
 - 文件I/O操作
 - GUI应用(保持界面响应)
 
协程的最佳场景
- 高并发网络服务(Web服务器)
 - 爬虫程序
 - 实时数据处理管道
 - 微服务通信
 
性能考量
| 指标 | 进程 | 线程 | 协程 | 
|---|---|---|---|
| 创建1000个 | 慢 | 中 | 极快 | 
| 上下文切换 | 慢 | 中 | 极快 | 
| 内存占用 | 高 | 中 | 极低 | 
| CPU利用率 | 高 | 低 | 中 | 
混合使用建议
在实际项目中,可以组合使用三种技术:
- 
进程池:处理CPU密集型任务
from concurrent.futures import ProcessPoolExecutor - 
线程池:处理阻塞I/O操作
from concurrent.futures import ThreadPoolExecutor - 
协程:处理高并发网络I/O
async def fetch(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text() 
特别提醒:Python的GIL问题
在CPython中,全局解释器锁(GIL)导致:
- 线程:同一时间只有一个线程执行Python字节码
 - 进程:每个进程有独立的GIL,可实现真并行
 - 协程:完全不受GIL影响(因为运行在单线程)
这是Python多线程在CPU密集型任务中表现不佳的根本原因。 
4.2 只有一个线程在执行,concurrent.futures为什么可以实现多线程呢
在Python中,虽然全局解释器锁(GIL)确实导致同一时刻只有一个线程可以执行Python字节码,但concurrent.futures的ThreadPoolExecutor仍然能实现有效的多线程并发,原因如下:
1. I/O密集型任务的本质
当线程执行I/O操作(如网络请求、文件读写、数据库查询)时:
- 线程会主动释放GIL,进入阻塞等待状态
 - 其他线程可以立即获取GIL并执行
 - 这种切换由操作系统调度,完全透明
 
# 示例:多线程高效处理I/O
with ThreadPoolExecutor(max_workers=5) as executor:
    executor.map(requests.get, urls)  # 每个线程在等待网络响应时都会释放GIL
效果:虽然Python字节码是串行执行的,但I/O等待时间被完美重叠利用,实现伪并行。
2. C扩展的规避能力
当线程调用C语言编写的扩展模块(如NumPy、zlib、加密库)时:
- 这些扩展可以在不持有GIL的情况下运行
 - 计算密集型任务也能获得真正的并行加速
 
# 示例:使用C扩展绕过GIL
import numpy as np
def compute():
    arr = np.random.rand(1000, 1000)  # NumPy运算会释放GIL
    return np.linalg.inv(arr)         # 矩阵求逆在C层并行
3. 操作系统线程的调度
ThreadPoolExecutor底层使用原生操作系统线程:
- Python线程 ≈ 操作系统线程
 - 虽然GIL限制Python字节码执行,但操作系统仍会公平调度所有线程
 - 当某个线程因I/O阻塞时,操作系统会立即切换上下文
 
4. 与多进程的对比
| 特性 | ThreadPoolExecutor | 
ProcessPoolExecutor | 
|---|---|---|
| GIL影响 | 受限制 | 完全绕过(每个进程独立GIL) | 
| 适合任务类型 | I/O密集型 | CPU密集型 | 
| 内存共享 | 直接共享 | 需IPC(队列/共享内存) | 
| 切换开销 | 较低(~1µs) | 较高(~100µs) | 
何时选择多线程?
- 任务主要是等待I/O(网络/磁盘/数据库)
 - 需要共享内存状态(如全局计数器)
 - 创建大量并发单元(线程比进程轻量)
 
# 典型用例:Web爬虫
def fetch(url):
    resp = requests.get(url)  # 每个请求都会释放GIL
    return resp.text
with ThreadPoolExecutor(50) as executor:  # 50个线程
    executor.map(fetch, urls)            # 并发处理URL列表
关键结论
- GIL不阻止多线程:它只限制Python字节码的并行执行,不影响I/O并发
 - 高效并发秘诀:利用I/O等待时间切换线程(类似协程原理)
 - 真正瓶颈:纯Python的CPU计算(此时应换用多进程)
 
通过合理利用I/O阻塞和C扩展,ThreadPoolExecutor能在GIL限制下仍提供出色的并发性能。
4.3 如何选择协程还是线程
| 特性 | 协程 (Coroutine) | 线程 (Thread) | 
|---|---|---|
| 并发模型 | 协作式(单线程内切换) | 抢占式(操作系统调度) | 
| 并发量 | 轻松支持数万级并发(如10K+连接) | 通常数百到数千(受线程栈内存限制) | 
| 切换开销 | 极低(用户态切换,约100ns) | 较高(内核态切换,约1µs) | 
| 内存占用 | 每个协程约几KB | 每个线程约8MB(默认栈大小) | 
| 编程复杂度 | 需要async/await语法,避免阻塞调用 | 传统同步代码,但需处理线程安全 | 
| 调试难度 | 较难(异步调用链复杂) | 中等(需处理竞态条件) | 
| 适用场景 | I/O密集型高并发(网络/磁盘) | I/O密集型中低并发、需兼容旧代码 | 
优先协程:如果是纯I/O密集型且能控制代码(如新项目)
妥协用线程:如需兼容旧代码或使用不支持异步的库
绝不混用:避免在同一应用中随意混用协程和线程(增加复杂度)
4.4 如何保证多线程安全
常见的处理方法包括使用互斥锁、可重入锁、信号量、线程局部存储、线程安全队列、线程池以及避免共享状态等。
线性池如何保证多线程安全
| 特性 | 手动线程管理 | 线程池 | 
|---|---|---|
| 任务分配 | 需自行实现安全队列 | 内置线程安全队列 | 
| 异常处理 | 需手动捕获传播 | 自动封装在Future中 | 
| 资源回收 | 需自行管理线程生命周期 | 自动重用线程 | 
| 结果收集 | 需实现同步机制 | 通过Future自动同步 | 
| 最大并发控制 | 需自行实现 | 内置max_workers参数控制 | 
4.5 多线程 + 多机器场景下的GIL
- 单机多线程:
即使有多个线程,GIL 会强制同一时刻仅一个线程运行Python代码(CPU密集型任务无法充分利用多核)。
I/O密集型任务(如网络请求、文件读写)可以绕过GIL,因为线程在等待I/O时会释放GIL。 - 多机器(或多进程):
如果任务分布在多台机器或多个Python进程上(每个机器/进程独立运行CPython),每个进程有自己的GIL,此时GIL不会跨进程/机器影响。
这种情况下,真正的并行成为可能(因为GIL是进程级的锁)。 
                    
                
                
            
        
浙公网安备 33010602011771号