Skip to content

进程 / 线程 / 协程与服务并发模型

💡 学习指南:并发编程是很多后端工程师的"阿喀琉斯之踵"——面试被问倒、线上出 Bug、性能调优没思路。本章节会围绕一个核心问题展开:当10万个用户同时请求你的服务,你的代码会崩吗?

在开始之前,建议你先补两块"基础砖":

  • CPU、内存、I/O 是什么:如果不清楚这些基础概念,可以先回顾操作系统的基本知识。
  • 什么是阻塞/非阻塞:如果还不熟悉同步/异步的概念,可以先通过实际编程体验感受一下。

0. 引言:为什么你的服务一到高峰期就"卡死"?

进程 / 线程 / 协程 对比演示

内存占用
400
MB
上下文切换
0
完成任务
0
耗时
0
ms
CPU 1
CPU 2
CPU 3
CPU 4
任务队列
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Task 7
Task 8
Task 9
Task 10
Task 11
Task 12
Task 13
Task 14
Task 15
Task 16

很多人在实际开发中都会遇到类似的情况:

  • 本地测试时服务响应飞快,一上线就"卡成 PPT";
  • 明明买了很高的服务器配置,CPU 占用率却总是上不去;
  • 一到促销高峰期,服务就"雪崩",不得不降级或熔断。

直觉上,我们会以为是:"服务器不够强"。 但大多数时候,问题并不在于硬件"不够快",而在于我们没有设计好并发模型

核心矛盾

  • 如果不并发处理:用户请求排队等待,体验极差;
  • 如果乱用多线程:锁竞争、上下文切换开销,性能反而下降。

面对这些挑战,单纯依靠"加机器"已经捉襟见肘。我们需要一套系统的并发设计方法,在高并发场景下既保证性能,又确保稳定性。这正是本章节试图解决的问题。


1. 核心概念:进程、线程、协程,到底啥区别?

1.1 一个餐厅的比喻

想象你开了一家餐厅,要同时服务很多顾客:

概念餐厅比喻技术含义
进程 (Process)独立的餐厅分店拥有独立的内存空间、资源分配,是操作系统资源分配的基本单位。一个进程崩溃不会影响其他进程。
线程 (Thread)分店内的厨师是 CPU 调度的基本单位,共享进程内的内存空间。同一进程内的线程可以共享数据,但一个线程崩溃可能导致整个进程崩溃。
协程 (Coroutine)厨师的"分身术"用户态的轻量级线程,由程序自己调度而非操作系统。切换开销极小,可以创建数百万个。

1.2 深入对比:三者的本质差异

进程内存隔离演示

系统内存

进程:资源隔离的"集装箱"

核心特点

  • 隔离性强:每个进程有独立的虚拟地址空间
  • 开销大:创建/切换需要操作系统介入,耗时约 1-10ms
  • 通信复杂:进程间通信(IPC)需要特殊机制(管道、消息队列、共享内存等)

适用场景

  • 需要强隔离的服务(如浏览器标签页、沙箱程序)
  • 多语言混合部署的服务
  • 需要独立重启/升级的服务单元

线程:共享内存的"轻骑兵"

线程调度演示

时间轴
0ms
100ms
200ms
300ms
400ms
500ms
0
已完成线程
0
上下文切换
0ms
平均等待时间
0
吞吐量 (线程/秒)
当前调度算法: Round Robin (时间片轮转)

每个线程轮流执行一个时间片,时间片用完就切换到下一个线程。响应性好,适合交互式系统。

核心特点

  • 共享内存:同一进程内的线程共享代码段、数据段、堆
  • 独立栈空间:每个线程有自己的栈(通常 1MB 左右)
  • 切换较快:线程切换约 1-10μs,比进程快 1000 倍
  • 需要同步:共享数据需要加锁保护

适用场景

  • CPU 密集型任务(计算、图像处理)
  • 需要共享大量数据的并发任务
  • 对延迟敏感的后台任务

协程:用户态的"绿色线程"

协程轻量级对比演示

1000 个协程
线程模型
内存占用
1000 MB
创建时间
100 ms
上下文切换
~1-10 μs
VS
协程模型
内存占用
2000 MB
创建时间
10 ms
上下文切换
~100 ns
🚀 节省 -100% 内存

核心特点

  • 用户态调度:由程序/运行时库调度,不经过操作系统
  • 极轻量级:协程栈通常只有几 KB,可创建数百万个
  • 切换极快:协程切换约 100ns,比线程快 100 倍
  • 非抢占式:协程主动让出 CPU(协作式多任务)

适用场景

  • I/O 密集型高并发服务(Web 服务器、网关)
  • 需要维持大量长连接的场景(IM、游戏服务器)
  • 流式数据处理、流水线作业

2. 案例分析:某电商大促的"并发之痛"

2.1 血泪教训:从"单机"到"分布式"的演进

让我们看一个真实的电商系统演进故事:

阶段一:单机时代(日活 1000)

python
# 简单的 Flask 应用
from flask import Flask

app = Flask(__name__)

@app.route('/order')
def create_order():
    # 查询库存
    stock = db.query("SELECT stock FROM products WHERE id=1")
    if stock > 0:
        # 扣减库存
        db.execute("UPDATE products SET stock = stock - 1 WHERE id=1")
        # 创建订单
        db.execute("INSERT INTO orders ...")
        return "Order created!"
    return "Out of stock!"

# 启动:flask run

问题

  • 单进程单线程,一次只能处理一个请求
  • 库存扣减没有加锁,并发时会出现超卖
  • 数据库连接数有限,连接池很快被耗尽

阶段二:多进程时代(日活 1万)

python
# 使用 Gunicorn 多进程部署
gunicorn -w 4 -k sync app:app

# 4个 worker 进程,每个进程独立处理请求

新问题

  • 4 个进程同时查库存,都看到 stock=1,都扣减成功,超卖 3 个!
  • 需要引入分布式锁
python
import redis

# 使用 Redis 分布式锁
lock = redis_client.lock("stock_lock", timeout=10)
if lock.acquire():
    try:
        stock = db.query("SELECT stock FROM products WHERE id=1")
        if stock > 0:
            db.execute("UPDATE products SET stock = stock - 1 WHERE id=1")
    finally:
        lock.release()

阶段三:协程时代(日活 10万)

python
# 使用 FastAPI + asyncio
from fastapi import FastAPI
import asyncio

app = FastAPI()

async def check_stock(product_id: int) -> int:
    # 异步查询数据库,不阻塞
    result = await db.fetch_one(
        "SELECT stock FROM products WHERE id = :id",
        {"id": product_id}
    )
    return result["stock"]

@app.get("/order")
async def create_order(product_id: int):
    # 并发检查库存和用户信息
    stock_task = check_stock(product_id)
    user_task = get_user_info(request.user_id)

    stock, user = await asyncio.gather(stock_task, user_task)

    if stock > 0:
        # 异步扣减库存
        await db.execute(
            "UPDATE products SET stock = stock - 1 WHERE id = :id",
            {"id": product_id}
        )
        return {"status": "success"}

    return {"status": "out_of_stock"}

# 启动:uvicorn main:app --workers 4
# 每个 worker 内可以处理数千个并发协程

优势

  • 单线程内可处理数千并发连接
  • I/O 操作时主动让出 CPU,不阻塞其他请求
  • 内存占用极低,适合高并发长连接场景

2.2 并发模型演进对比表

阶段并发模型支撑日活核心问题解决方案
单体单进程单线程1K无法并发处理引入多进程
多进程多进程同步10K数据竞争、超卖分布式锁
多线程多线程+锁50K上下文切换开销、死锁线程池、无锁队列
协程异步 I/O100K+代码复杂度、调试困难框架封装、链路追踪
混合多进程+协程1000K+架构复杂度服务治理、弹性伸缩

3. 原理深入:各种并发模型的工作原理

3.1 进程模型:隔离性与通信

内存隔离机制

进程内存隔离演示

系统内存

每个进程拥有独立的虚拟地址空间:

进程 A 的虚拟内存          进程 B 的虚拟内存
+----------------+        +----------------+
|  内核空间      |        |  内核空间      |  <-- 共享(只读)
|  (共享)        |        |  (共享)        |
+----------------+        +----------------+
|  栈空间        |        |  栈空间        |  <-- 独立
|  (向下增长)    |        |  (向下增长)    |
+----------------+        +----------------+
|  堆空间        |        |  堆空间        |  <-- 独立
|  (向上增长)    |        |  (向上增长)    |
+----------------+        +----------------+
|  数据段        |        |  数据段        |  <-- 独立
|  (.bss/.data)  |        |  (.bss/.data)  |
+----------------+        +----------------+
|  代码段        |        |  代码段        |  <-- 独立
|  (.text)       |        |  (.text)       |
+----------------+        +----------------+

进程间通信(IPC)方式

方式原理速度适用场景
管道 (Pipe)内核缓冲区,单向流中等父子进程间通信
消息队列内核消息链表中等异步消息传递
共享内存同一块物理内存映射最快大量数据共享
信号量内核计数器-同步与互斥
Socket网络协议栈较慢跨机器通信
信号 (Signal)软中断-事件通知

3.2 线程模型:调度与同步

线程调度原理

线程调度演示

时间轴
0ms
100ms
200ms
300ms
400ms
500ms
0
已完成线程
0
上下文切换
0ms
平均等待时间
0
吞吐量 (线程/秒)
当前调度算法: Round Robin (时间片轮转)

每个线程轮流执行一个时间片,时间片用完就切换到下一个线程。响应性好,适合交互式系统。

操作系统线程调度器的基本工作:

就绪队列                    运行中                    等待队列
+--------+                +--------+               +--------+
| 线程 B |  <-- 时间片到   | 线程 A |  <-- I/O请求  | 线程 C |
| 线程 D |                | (运行) |               | 线程 E |
| 线程 F |                +--------+               | (阻塞) |
+--------+                                         +--------+
    |                                                  |
    v                                                  v
调度器根据优先级选择下一个运行            I/O完成时移回就绪队列

常见线程同步机制

机制原理优点缺点
互斥锁 (Mutex)二元状态,独占访问实现简单竞争激烈时性能差
读写锁 (RWLock)读共享,写独占读多写少场景效率高实现复杂,有写饥饿风险
自旋锁 (Spinlock)忙等待,不释放 CPU等待时间短时效率高等待时间长时浪费 CPU
条件变量等待特定条件满足避免忙等待需要配合锁使用
信号量 (Semaphore)计数器控制访问数量可控制并发数使用不当易出错
原子操作CPU 指令级原子性无锁,性能最高只能操作简单数据类型
无锁队列CAS 操作实现高并发下性能优异实现复杂,ABA 问题

3.3 协程模型:用户态调度

协程轻量级对比演示

1000 个协程
线程模型
内存占用
1000 MB
创建时间
100 ms
上下文切换
~1-10 μs
VS
协程模型
内存占用
2000 MB
创建时间
10 ms
上下文切换
~100 ns
🚀 节省 -100% 内存

协程的核心优势

传统多线程                vs              协程模型

+------------+                       +------------+
|  线程 1    |                       |  事件循环   |
| (1MB栈)   |                       |  (调度器)   |
+------------+                       +------------+
     |                                     |
     v                                     v
+------------+                       +------------+
|  线程 2    |                       |  协程 A    |
| (1MB栈)   |                       | (几KB栈)   |
+------------+                       +------------+
     |                                     |
     v                                     v
+------------+                       +------------+
|  线程 3    |                       |  协程 B    |
| (1MB栈)   |                       | (几KB栈)   |
+------------+                       +------------+

开销:N MB                           开销:N KB
创建:~10μs                         创建:~100ns
切换:~1μs                          切换:~100ns

async/await 的工作机制

async/await 机制演示

Python asyncio 示例
import asyncio

async def fetch_data(url):
    # await 挂起,让出 CPU
    response = await aiohttp.get(url)
    # I/O 完成后继续执行
    return response.json()

async def main():
    # 并发执行
    tasks = [fetch_data(url) for url in urls]
    results = await asyncio.gather(*tasks)
执行时间线
0ms
50ms
100ms
150ms
200ms
事件循环
调度中
任务 1
执行
I/O
执行
I/O
执行
I/O
任务 2
执行
I/O
执行
I/O
执行
I/O
任务 3
执行
I/O
执行
I/O
执行
I/O
任务 4
执行
I/O
执行
I/O
执行
I/O
任务 5
执行
I/O
执行
I/O
执行
I/O
并发任务数
5
总执行时间
100ms
I/O 等待时间
60ms
CPU 利用率
40%
python
import asyncio

async def fetch_data(url):
    # 遇到 await,协程挂起,让出 CPU
    response = await aiohttp.get(url)
    # I/O 完成后,事件循环唤醒协程,从这里继续执行
    return response.json()

async def main():
    # 创建 3 个协程任务
    tasks = [
        fetch_data("https://api1.example.com"),
        fetch_data("https://api2.example.com"),
        fetch_data("https://api3.example.com")
    ]
    # 并发执行,总耗时 ≈ 最慢的那个请求
    results = await asyncio.gather(*tasks)
    return results

# 启动事件循环
asyncio.run(main())

执行流程

时间线 -------------------------------------------------------------------->

协程 A: [准备请求]--[await 挂起]=======[收到响应]--[处理数据]
                     |
协程 B:              [准备请求]--[await 挂起]=======[收到响应]--[处理数据]
                                  |
协程 C:                           [准备请求]--[await 挂起]=======[收到响应]
                                               |

                                         所有 I/O 完成

说明:[ ] 表示 CPU 执行, === 表示 I/O 等待, | 表示协程切换

3.4 事件循环:协程的"心脏"

事件循环 (Event Loop) 演示

调用栈 (Call Stack)
栈为空
事件循环 (Event Loop)
检查
1执行调用栈中的同步代码
2执行所有微任务 (microtasks)
3渲染 UI (如果需要)
4执行宏任务 (macrotask)
任务队列
微任务队列 (Microtasks)
队列为空
宏任务队列 (Macrotasks)
队列为空

事件循环是协程调度的核心机制:

python
import selectors
import heapq

class EventLoop:
    def __init__(self):
        self.selector = selectors.DefaultSelector()
        self.ready = []  # 就绪队列
        self.scheduled = []  # 定时任务队列
        self.current = None

    def run(self):
        while True:
            # 1. 处理定时任务
            now = time.time()
            while self.scheduled and self.scheduled[0][0] <= now:
                _, callback = heapq.heappop(self.scheduled)
                self.ready.append(callback)

            # 2. 等待 I/O 事件
            timeout = 0 if self.ready else 0.1
            events = self.selector.select(timeout)

            for key, mask in events:
                callback = key.data
                self.ready.append(callback)

            # 3. 执行就绪的回调
            while self.ready:
                callback = self.ready.popleft()
                callback()

3.5 并发 vs 并行:不是一回事

并发 (Concurrency) vs 并行 (Parallelism) 演示

CPU 核心 (单核)
CPU 1
空闲
CPU 2
空闲
CPU 3
空闲
CPU 4
空闲
任务执行
任务 1
40ms
任务 2
30ms
任务 3
50ms
任务 4
35ms
并发 vs 并行 对比
🔄
并发 (Concurrency)
多个任务交替执行,宏观上同时推进
例子: 单核CPU多线程、协程调度、异步I/O
并行 (Parallelism)
多个任务真正同时执行
例子: 多核CPU计算、GPU并行计算、分布式处理
需要什么条件?
并发: 单核 CPU 即可实现
并行: 需要多核 CPU 或多台机器
概念英文含义比喻需要条件
并发Concurrency多个任务交替执行,宏观上同时推进一个人轮流做多个菜单核 CPU 即可
并行Parallelism多个任务真正同时执行多个人同时做不同的菜多核 CPU 或多机

图示说明

单核 CPU - 并发(Concurrent)
时间 →  1    2    3    4    5    6    7    8
任务 A: [执行][执行]      [执行][执行]
任务 B:      [执行][执行]      [执行][执行]

两个任务交替执行,宏观上"同时"推进

========================================

多核 CPU - 并行(Parallel)
时间 →  1    2    3    4    5    6    7    8
核心 1: [任务A][任务A][任务A][任务A]
核心 2: [任务B][任务B][任务B][任务B]

两个任务真正"同时"执行

========================================

现实中往往是:并发 + 并行
时间 →  1    2    3    4    5    6    7    8
核心 1: [A1][A1][B1][B1][C1][C1][D1][D1]
核心 2: [A2][A2][B2][B2][C2][C2][D2][D2]

多个任务先并发调度到不同核心,再在核心上并行执行

4. 实战:Go 协程与绿色线程

4.1 Go 的并发哲学

Go 协程 (Goroutine) 与 GMP 调度演示

Global Queue (G)3
G1
G2
G3
P (Processors) - 4 个
P0运行中
本地队列
G4
G5
G6
绑定 M0
P1空闲
本地队列
G7
G8
G9
P2空闲
本地队列
G10
G11
G12
P3空闲
本地队列
-
M (Machine Threads) - 4 个
M0运行中
M1休眠
M2休眠
M3休眠

Go 语言的并发设计哲学:不要通过共享内存来通信,而要通过通信来共享内存

go
package main

import (
    "fmt"
    "time"
)

// 生产者
func producer(ch chan<- int, id int) {
    for i := 0; i < 5; i++ {
        fmt.Printf("Producer %d sending: %d\n", id, i)
        ch <- i  // 发送数据到 channel
        time.Sleep(100 * time.Millisecond)
    }
}

// 消费者
func consumer(ch <-chan int, id int) {
    for val := range ch {  // 从 channel 接收数据
        fmt.Printf("Consumer %d received: %d\n", id, val)
    }
}

func main() {
    // 创建带缓冲的 channel
    ch := make(chan int, 10)

    // 启动 2 个生产者 goroutine
    for i := 0; i < 2; i++ {
        go producer(ch, i)
    }

    // 启动 2 个消费者 goroutine
    for i := 0; i < 2; i++ {
        go consumer(ch, i)
    }

    // 等待一段时间
    time.Sleep(3 * time.Second)
    close(ch)
}

4.2 Goroutine 调度器:GMP 模型

Go 的调度器采用了 GMP 模型:

组件含义作用
G (Goroutine)协程待执行的任务,轻量级(2KB 栈,可动态伸缩)
M (Machine)系统线程实际执行 G 的载体,与内核线程 1:1 对应
P (Processor)逻辑处理器调度上下文,包含可运行的 G 队列,数量默认等于 CPU 核心数

调度流程

全局队列
+----------------+
|  G1  |  G2  |  G3  |
+----------------+

P0 的本地队列       P1 的本地队列       P2 的本地队列       P3 的本地队列
+----------+       +----------+       +----------+       +----------+
| G4 | G5  |       | G6 | G7  |       | G8 | G9  |       | G10| G11 |
+----------+       +----------+       +----------+       +----------+
    |                     |                     |                     |
    v                     v                     v                     v
+----------+       +----------+       +----------+       +----------+
|    M0    |       |    M1    |       |    M2    |       |    M3    |
| (OS线程) |       | (OS线程) |       | (OS线程) |       | (OS线程) |
+----------+       +----------+       +----------+       +----------+

调度策略:
1. 每个 P 维护一个本地 G 队列,减少锁竞争
2. P 从本地队列取 G 交给 M 执行
3. 本地队列空时,从其他 P"偷"一半的 G(Work Stealing)
4. 全局队列作为兜底,每隔一段时间检查一次

5. 实战代码模板

5.1 Python asyncio 高并发模板

python
import asyncio
import aiohttp
from typing import List, Dict
import time

class AsyncHTTPClient:
    """基于 asyncio 的高性能 HTTP 客户端"""

    def __init__(self, max_connections: int = 100, timeout: int = 30):
        self.timeout = aiohttp.ClientTimeout(total=timeout)
        # 限制并发连接数,防止把对方服务打挂
        connector = aiohttp.TCPConnector(
            limit=max_connections,
            limit_per_host=10,  # 对单个域名的连接限制
            enable_cleanup_closed=True,
            force_close=True,
        )
        self.session = aiohttp.ClientSession(
            connector=connector,
            timeout=self.timeout,
        )

    async def fetch(self, url: str, method: str = 'GET', **kwargs) -> Dict:
        """发送单个请求"""
        try:
            async with self.session.request(method, url, **kwargs) as response:
                return {
                    'url': url,
                    'status': response.status,
                    'data': await response.text(),
                    'error': None
                }
        except asyncio.TimeoutError:
            return {'url': url, 'status': None, 'data': None, 'error': 'Timeout'}
        except Exception as e:
            return {'url': url, 'status': None, 'data': None, 'error': str(e)}

    async def fetch_many(self, urls: List[str], concurrency: int = 10) -> List[Dict]:
        """并发获取多个 URL,限制并发数"""
        semaphore = asyncio.Semaphore(concurrency)

        async def fetch_with_limit(url):
            async with semaphore:
                return await self.fetch(url)

        # 并发执行所有请求
        tasks = [fetch_with_limit(url) for url in urls]
        return await asyncio.gather(*tasks, return_exceptions=True)

    async def close(self):
        await self.session.close()


# 使用示例
async def main():
    client = AsyncHTTPClient(max_connections=50)

    # 要抓取的 URL 列表
    urls = [
        "https://api.github.com/users/github",
        "https://api.github.com/users/google",
        "https://api.github.com/users/microsoft",
        # ... 更多 URL
    ] * 10  # 模拟 300 个请求

    start = time.time()
    results = await client.fetch_many(urls, concurrency=20)
    elapsed = time.time() - start

    # 统计结果
    success = sum(1 for r in results if r.get('status') == 200)
    failed = len(results) - success

    print(f"总请求数: {len(results)}")
    print(f"成功: {success}, 失败: {failed}")
    print(f"耗时: {elapsed:.2f}s")
    print(f"QPS: {len(results)/elapsed:.1f}")

    await client.close()

if __name__ == "__main__":
    asyncio.run(main())

5.2 Go 高并发服务模板

go
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"runtime"
	"time"

	"golang.org/x/sync/errgroup"
)

// Request/Response 结构
type OrderRequest struct {
	UserID    int64   `json:"user_id"`
	ProductID int64   `json:"product_id"`
	Quantity  int     `json:"quantity"`
	Price     float64 `json:"price"`
}

type OrderResponse struct {
	OrderID   int64   `json:"order_id"`
	Status    string  `json:"status"`
	Total     float64 `json:"total"`
	CreatedAt string  `json:"created_at"`
}

// 模拟数据库操作
type Database struct {
	orders map[int64]*OrderResponse
	mutex  chan struct{}
}

func NewDatabase() *Database {
	db := &Database{
		orders: make(map[int64]*OrderResponse),
		mutex:  make(chan struct{}, 1), // 模拟互斥锁
	}
	return db
}

func (db *Database) CreateOrder(ctx context.Context, req *OrderRequest) (*OrderResponse, error) {
	// 获取锁
	select {
	case db.mutex <- struct{}{}:
		defer func() { <-db.mutex }()
	case <-ctx.Done():
		return nil, ctx.Err()
	}

	// 模拟数据库操作延迟
	select {
	case <-time.After(50 * time.Millisecond):
	case <-ctx.Done():
		return nil, ctx.Err()
	}

	order := &OrderResponse{
		OrderID:   time.Now().UnixNano(),
		Status:    "created",
		Total:     req.Price * float64(req.Quantity),
		CreatedAt: time.Now().Format(time.RFC3339),
	}
	db.orders[order.OrderID] = order
	return order, nil
}

// HTTP 处理器
type Handler struct {
	db *Database
}

func NewHandler(db *Database) *Handler {
	return &Handler{db: db}
}

func (h *Handler) CreateOrder(w http.ResponseWriter, r *http.Request) {
	// 设置请求超时
	ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
	defer cancel()

	var req OrderRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	order, err := h.db.CreateOrder(ctx, &req)
	if err != nil {
		if err == context.DeadlineExceeded {
			http.Error(w, "Request timeout", http.StatusGatewayTimeout)
			return
		}
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(order)
}

func (h *Handler) Health(w http.ResponseWriter, r *http.Request) {
	info := map[string]interface{}{
		"status":    "ok",
		"goroutine": runtime.NumGoroutine(),
		"cpu":       runtime.NumCPU(),
		"version":   runtime.Version(),
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(info)
}

// 批量处理示例
func BatchProcess(ctx context.Context, items []int) ([]int, error) {
	g, ctx := errgroup.WithContext(ctx)
	g.SetLimit(10) // 限制并发数为 10

	results := make([]int, len(items))

	for i, item := range items {
		i, item := i, item // 避免闭包陷阱
		g.Go(func() error {
			select {
			case <-ctx.Done():
				return ctx.Err()
			default:
				// 模拟处理
				time.Sleep(100 * time.Millisecond)
				results[i] = item * 2
				return nil
			}
		})
	}

	if err := g.Wait(); err != nil {
		return nil, err
	}
	return results, nil
}

func main() {
	// 初始化数据库
	db := NewDatabase()

	// 创建处理器
	handler := NewHandler(db)

	// 设置路由
	mux := http.NewServeMux()
	mux.HandleFunc("/order", handler.CreateOrder)
	mux.HandleFunc("/health", handler.Health)

	// 创建服务器
	server := &http.Server{
		Addr:         ":8080",
		Handler:      mux,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  120 * time.Second,
	}

	fmt.Println("Server starting on :8080")
	fmt.Printf("Go version: %s\n", runtime.Version())
	fmt.Printf("CPU cores: %d\n", runtime.NumCPU())

	if err := server.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

6. 总结对照表

6.1 核心概念对比

特性进程线程协程
调度者操作系统操作系统用户程序/运行时
切换开销~1-10ms~1-10μs~100ns
内存占用~10MB+~1MB~2KB
通信方式IPC共享内存共享内存/Channel
同步需求不需要需要锁需要锁/协作式
崩溃影响仅本进程整个进程可控制
适用场景强隔离、多租户CPU 密集型I/O 密集型
典型语言所有语言所有语言Go、Python、JS、Rust

6.2 并发模型选型指南

场景推荐模型理由
Web 服务网关协程 + 异步 I/O高并发连接,低内存占用
实时通信服务协程 + 长连接维持大量 WebSocket 连接
数据处理管道多进程 + 协程利用多核,I/O 不阻塞
科学计算多线程/多进程CPU 密集型,需要并行计算
微服务架构多进程 + 协程服务间隔离,内部高并发
嵌入式系统协程/单线程资源受限,确定性调度

6.3 名词对照表

英文术语中文对照解释
Process进程操作系统资源分配的基本单位,拥有独立的内存空间
Thread线程CPU 调度的基本单位,共享进程内存空间
Coroutine协程用户态轻量级线程,由程序自主调度
Concurrency并发多个任务交替执行,宏观上同时推进
Parallelism并行多个任务真正同时执行,需要多核支持
Context Switch上下文切换CPU 从一个任务切换到另一个任务的过程
Blocking I/O阻塞 I/O发起 I/O 请求后等待完成,期间线程挂起
Non-blocking I/O非阻塞 I/O发起 I/O 请求后立即返回,不等待结果
Async I/O异步 I/OI/O 完成时通过回调或通知机制告知调用者
Event Loop事件循环协程调度机制,持续监听事件并分发处理
GoroutineGo 协程Go 语言的轻量级线程实现
Channel通道Go 语言中协程间通信的机制
Mutex互斥锁用于保护共享资源的同步原语
Semaphore信号量控制同时访问某资源的线程数量
Deadlock死锁多个线程互相等待对方释放资源,导致永久阻塞
Race Condition竞态条件多个线程同时访问共享数据,导致结果不确定
Thread Pool线程池预先创建一组线程,复用以减少创建销毁开销
Work Stealing工作窃取空闲线程从忙碌线程的队列中"偷"任务执行
Zero-copy零拷贝数据在内核态和用户态之间传输时不经过 CPU 拷贝
C10K ProblemC10K 问题单机同时处理 1 万个连接的挑战
C10M ProblemC10M 问题单机同时处理 1000 万个连接的终极挑战

7. 写在最后

7.1 并发编程的黄金法则

  1. 不要过早优化:先让代码正确运行,再考虑性能优化
  2. 避免共享状态:"不要通过共享内存来通信,而要通过通信来共享内存"
  3. 让错误尽早暴露:并发 Bug 往往难以复现,要在测试阶段尽可能暴露
  4. 限制并发数:无限并发等于没有保护,要用信号量或连接池限制
  5. 监控和可观测:并发系统必须有完善的监控,才能快速定位问题

7.2 学习路线图

阶段 1: 基础理解
    ├── 理解进程/线程的基本概念
    ├── 学习同步原语(锁、信号量、条件变量)
    └── 编写简单的多线程程序

阶段 2: 深入原理
    ├── 理解内存模型和可见性
    ├── 学习无锁编程和原子操作
    ├── 理解线程池和工作窃取
    └── 分析死锁和竞态条件

阶段 3: 高级应用
    ├── 掌握协程和异步编程
    ├── 学习 Go/Python/Rust 的并发模型
    ├── 理解分布式系统中的并发
    └── 性能调优和容量规划

阶段 4: 专家水平
    ├── 设计高并发系统架构
    ├── 解决复杂的并发 Bug
    ├── 开发并发编程框架
    └── 分享和传播并发知识

希望这篇指南能帮助你建立起对并发编程的系统认知。记住,并发不是目的,而是手段——真正的目标是构建高性能、高可用的服务。理解原理、选对模型、写好代码,你就能在并发这条路上越走越远。