1.为什么选用fastapi?
"当时选择 FastAPI,主要是结合项目的业务特点、开发效率和后期维护成本综合考虑的。
第一,我们的项目以接口服务为主 ,比如前后端分离、微服务调用、数据处理接口这类场景比较多,FastAPI 本身就是围绕高性能 API 设计的,比较契合。
第二,文档和调试方便。FastAPI 会自动生成 Swagger/OpenAPI 文档,这对前后端协作、接口测试、后续维护都很有帮助。
第三,性能比传统 Python Web 框架更适合高并发接口场景 。因为它底层基于 ASGI,异步支持比较好。虽然我们项目不一定追求极限性能,但在高并发请求、IO 密集型场景下,它能提供比较好的扩展性。
第四,项目复杂度合适。项目是做 API 服务,而不是复杂服务端页面渲染,FastAPI 会比 Django 更轻;相比 Flask,它在参数校验、文档规范、工程化方面又更完善,综合下来选了 FastAPI。"
1. 为什么不用 Flask?
"Flask 更轻量,也很灵活,但很多能力要自己补,比如参数校验、接口文档、请求体模型定义这些。项目一旦接口多起来,规范和维护成本会上升。FastAPI 在这方面更工程化,适合中大型 API 项目。"
2. 为什么不用 Django?
"Django 更适合那种大而全的后台系统,像 ORM、Admin、模板渲染这些都很完整。但我们的项目核心诉求是提供 API 服务,不太需要那么重的框架能力,所以 FastAPI 更轻、更贴合需求。
一个更有"项目感"的回答方式
不要只背框架优点,最好加上项目背景:
"我们这个项目本质上是一个接口型项目,主要负责 XXX,比如数据查询、任务提交、结果返回这类功能。因为接口数量比较多,而且前后端联调频繁,所以我们希望框架能同时满足三个点:开发快、接口规范、后期好维护。FastAPI 刚好在这几个方面比较平衡,所以最后选了它。"
这里把 XXX 换成你的项目实际内容,效果会更好。
最推荐你的最终版本
"当时选 FastAPI,主要是因为我们的项目是典型的 API 服务场景。相比 Flask,它自带更完善的参数校验和自动文档生成功能,能减少很多重复开发,也方便前后端联调;相比 Django,它更轻量,不会引入我们暂时用不到的整套功能。另外它对异步支持更好,后面如果有高并发或者 IO 密集型接口,也更容易扩展。所以从业务匹配度、开发效率和维护成本几个角度看,FastAPI 是比较合适的选择。"
FastAPI 基于 Starlette(ASGI的框架实现),并实现了 ASGII(Asynchronous Server Gateway Interface) 规范,运行在 Uvicorn、Hypercorn 这类 ASGI server 上,也可以直接接入 ASGI middleware
FastAPI :基于 ASGI
Flask :传统上基于 WSGI
Django :历史上主要是 WSGI ,现在同时支持 WSGI 和 ASGI。
不过也要注意一个细节:基于 ASGI 不等于一定更快 。如果代码里大量是 CPU 密集型计算,或者虽然写了 async 但里面调用的都是阻塞库,那优势就不会自动出现。ASGI 的优势主要体现在高并发、网络 IO、数据库 IO、外部服务调用这类场景上。
2.进程、线程、协程的区别?
进程解决资源隔离和多核利用,线程解决进程内并发,协程解决高并发 IO 效率问题
从调度和资源两个角度看。进程是独立运行的程序实例,有自己的内存空间,隔离性最好;线程是进程里的执行单元,多个线程共享进程资源,创建和切换比进程更轻,但需要考虑线程安全;协程则更轻,它不是操作系统调度,而是程序在用户态自行切换,所以在高并发 IO 场景下效率很高。
从语言实现上看,Java 长期是以线程作为主要并发模型,配合线程池、锁和并发包使用;Python 则因为 GIL 的存在,多线程更适合 IO 密集型任务,CPU 密集型通常会用多进程,而在 Web 和网络编程里,Python 也大量使用 async/await 协程模型
什么时候协程性能明显优于线程?
看任务是不是以等待为主。协程最适合高并发 IO 密集型场景,比如 HTTP 请求、数据库查询、缓存访问、消息队列、WebSocket 长连接等。这类任务本身计算不重,但等待时间长,如果用线程,大量线程会带来比较高的内存占用 和上下文切换成本 ;而协程是用户态调度,创建和切换都更轻,可以在一个线程里管理大量任务,所以当并发量达到几千、几万级别时,性能和资源利用率往往会明显优于线程。如果任务主要是 CPU 计算,或者代码里大量阻塞调用,协程优势就不明显。
协程的优势不在于单个任务执行更快,而在于高并发等待场景下,整体吞吐更高、资源消耗更低
3.Synchronized和Lock的区别(Java)?
Java 里的 synchronized 是JVM内置同步机制,优点是简单、安全,进入同步块自动加锁,退出自动释放,适合简单场景;Lock 以 ReentrantLock 为代表,是 JUC(java.util.concurrent) 提供的显式锁,底层通过AQS实现,虽然需要手动释放,但功能更丰富,支持尝试加锁、可中断、公平锁以及多个条件变量,在复杂并发控制中更常用。(即Synchronized底层不使用AQS实现)
4.CAS、AQS?
1. AQS(AbstractQueuedSynchronizer) 的本质
AQS 是一个同步器模板 。它不直接是锁,而是实现锁的基础框架。
Java 已经帮你把"排队、阻塞、唤醒、状态管理"这一套通用逻辑写好了
具体你要实现独占锁、共享锁、计数器、信号量,只需要在它的基础上扩展。
2. AQS 核心由什么组成
state
一个 volatile int state这个 state 表示同步状态,比如:
- 在
ReentrantLock里,state 可以表示锁有没有被占用、重入次数 - 在
Semaphore里,state 可以表示剩余许可数
CLH 变体等待队列
如果线程抢资源失败,就进入 AQS 维护的一个双向队列里等待。
大致过程是:尝试获取资源->获取失败->入队->阻塞->前面线程释放资源后,唤醒队列中后继线程
3. AQS 支持两种模式
独占模式------同一时刻只允许一个线程拿到资源
典型例子:ReentrantLock
共享模式------多个线程可以同时获取资源
典型例子:Semaphore、CountDownLatch、ReentrantReadWriteLock 里的读锁
CAS 和 AQS 的关系:
AQS 底层会用 CAS 来操作 state 和队列状态。
- CAS 是原子操作手段
- AQS 是基于这些原子操作构建出来的同步框架
"CAS 是 Compare And Swap,一种无锁原子更新机制。它会先比较内存值和预期值是否一致,一致才更新,否则失败重试,所以常用于 AtomicInteger 这类原子类。AQS 是 AbstractQueuedSynchronizer,是 Java 并发包里实现锁和同步器的核心框架,它通过一个 state 状态字段和一个等待队列来管理线程获取和释放同步资源。很多锁,比如 ReentrantLock、Semaphore、CountDownLatch,底层都是基于 AQS 实现的。简单说,CAS 是底层原子操作,AQS 是基于 CAS 构建出来的同步框架。"