跳转到内容

Goroutine

GoroutineGo语言中实现并发编程的轻量级线程,由Go运行时管理。与操作系统线程相比,goroutine的创建和切换开销极小,使得开发者可以轻松创建成千上万的并发任务。

概述[编辑 | 编辑源代码]

Goroutine具有以下核心特性:

  • 轻量级 - 初始栈大小仅2KB(可动态扩容)
  • 低成本 - 创建和调度由Go运行时管理,不直接依赖OS线程
  • 通信机制 - 通过channel实现安全的goroutine间通信
  • 调度模型 - 采用M:N调度模型(M个goroutine映射到N个OS线程)

基本用法[编辑 | 编辑源代码]

使用go关键字即可启动goroutine:

package main

import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 3; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")  // 启动goroutine
    say("hello")     // 主goroutine
}

输出示例:

hello
world
hello
world
hello
world

调度原理[编辑 | 编辑源代码]

Go运行时使用GMP调度模型

Goroutine队列
逻辑处理器P
OS线程M
CPU核心

  • G (Goroutine):待执行的任务
  • M (Machine):操作系统线程
  • P (Processor):调度上下文,包含本地运行队列

同步机制[编辑 | 编辑源代码]

Channel通信[编辑 | 编辑源代码]

channel是goroutine间通信的主要方式:

func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    done <- true  // 发送完成信号
}

func main() {
    done := make(chan bool)
    go worker(done)
    <-done  // 阻塞等待结果
}

WaitGroup同步[编辑 | 编辑源代码]

sync.WaitGroup用于等待一组goroutine完成:

var wg sync.WaitGroup

func worker(id int) {
    defer wg.Done()
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
}

func main() {
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker(i)
    }
    wg.Wait()  // 等待所有worker完成
}

最佳实践[编辑 | 编辑源代码]

1. 避免goroutine泄漏(确保所有goroutine都能退出) 2. 使用带缓冲的channel处理生产-消费模式 3. 限制并发数量(如使用semaphore模式) 4. 优先使用context处理取消和超时

性能特点[编辑 | 编辑源代码]

对比传统线程:

特性 Goroutine OS线程
创建开销 ~2-4µs ~1ms
内存占用 初始2KB 默认1-8MB
切换成本 ~200ns ~1µs

实际应用[编辑 | 编辑源代码]

Web服务器[编辑 | 编辑源代码]

处理HTTP请求的典型模式:

func handleRequest(w http.ResponseWriter, r *http.Request) {
    go processRequest(r)  // 异步处理
    w.Write([]byte("请求已接收"))
}

并行计算[编辑 | 编辑源代码]

使用worker池处理任务:

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        results <- j * 2  // 处理任务
    }
}

func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)

    // 启动3个worker
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // 发送任务
    for j := 1; j <= 9; j++ {
        jobs <- j
    }
    close(jobs)

    // 收集结果
    for a := 1; a <= 9; a++ {
        <-results
    }
}

参见[编辑 | 编辑源代码]