goroutine | 青训营

100 阅读2分钟

详解goroutine

什么是 goroutine?

Goroutine 是 Go 语言中一种轻量级的并发执行单元,可以看作是一种比线程更轻量级的并发模型。Goroutine 在 Go 语言中被广泛用于处理并发任务,使得编写高效、高并发的程序变得更加容易。

特点和优势

  1. 轻量级 Goroutine 是非常轻量级的执行单位,相比操作系统线程,它们的创建和销毁开销更小。
  2. 低成本 在 Go 语言中,可以创建成千上万个 Goroutine 而不会产生明显的性能负担。
  3. 协作式调度 Goroutine 之间的切换由 Go 运行时负责,调度器会根据任务的状况自动在 Goroutine 之间进行切换,而不需要显式的线程同步。
  4. 通信通过共享内存 Goroutine 之间的通信通过共享内存进行,而不是通过传统的线程同步原语(如锁)来实现,这有助于减少了死锁和竞争条件的发生。
  5. 并行执行 在多核系统中,多个 Goroutine 可以并行执行,充分利用硬件资源。

创建 Goroutine:

在 Go 语言中,使用关键字 go 可以创建一个 Goroutine。例如:

func main() {
    go func() {
        // 这里是 Goroutine 执行的代码
    }()
    // 主 Goroutine 的代码
}

上述代码中,通过 go 关键字,我们创建了一个匿名函数的 Goroutine。

Goroutine 通信

Goroutine 之间可以通过通道(Channel)进行通信,通道是一种类型安全的并发数据结构,用于在 Goroutine 之间传递数据。通道可以通过 make 函数创建,然后使用 <- 操作符来发送和接收数据。例如:

func main() {
    ch := make(chan int)  // 创建一个整数类型通道
    go func() {
        ch <- 42  // 发送数据到通道
    }()
    value := <-ch  // 从通道接收数据
    fmt.Println(value)  // 输出:42
}

Goroutine 调度

Go 运行时(runtime)会负责 Goroutine 的调度。调度器会根据一定的策略在多个 Goroutine 之间进行切换,以实现并发执行。调度器会在 Goroutine 阻塞时,切换到其他可执行的 Goroutine。这种协作式调度避免了多线程程序中的死锁和饥饿问题。

注意事项

  1. Goroutine 之间的共享数据访问需要谨慎处理,可以使用通道来避免竞态条件。
  2. 确保主 Goroutine 不会在其他 Goroutine 执行之前退出,可以使用等待组(sync.WaitGroup)来同步等待所有 Goroutine 完成。
  3. 不要滥用 Goroutine,过多的 Goroutine 可能会导致内存和性能问题。

总结

Goroutine 是 Go 语言并发模型的核心,它的轻量级、协作式调度和通信机制使得编写高效、高并发的程序变得更加简单。通过合理地使用 Goroutine 和通道,可以充分发挥多核处理器的性能,并避免常见的并发问题。