跟着 GPT-4 从0到1学习 Golang 并发机制(一)

这篇博客通过与GPT-4的交互,详细介绍了Golang的并发机制,重点讨论了Goroutines与线程的区别、调度开销、用户态与内核态的概念,以及Select语句的使用和default的应用场景。Goroutines作为Go语言轻量级线程,由Go运行时管理,相比线程创建和销毁开销小,调度更高效。Select语句用于在多个channel操作中选择,default则在无case可执行时提供备选操作。
摘要由CSDN通过智能技术生成

一、前言

今天玩点不一样的,我想试试看 GPT-4 能不能当好一个编程老师,循循善诱,由浅入深,深入浅出…… 给我讲解下 Golang 里的并发机制。

今天倒掉腹中半杯水,当回白纸,GPT 为笔,代码为颜料,挥笔泼墨,且看能绘出怎样的世界。

二、开聊

下文通过 DevChat 和 GPT-4 交互,如果你对 DevChat 感兴趣,可以跳转下文浏览:

2.1 Golang 里的并发机制介绍

  • 在 DevChat 里和 GPT-4 交互的体验:

下文主要贴文字,避免过多使用截图。

  • 我问 GPT:

能不能介绍下 Golang 里的并发机制

  • GPT 说:

在 Golang 中,主要的并发机制是通过 Goroutines 和 Channels 实现的。

  1. Goroutines:Goroutines 是 Go 语言中的轻量级线程实现,由 Go 运行时环境管理。Goroutines 相比于线程的优势在于其创建和销毁的开销小,可以轻松创建上百万个而不会导致系统资源耗尽。创建一个 Goroutine 只需要在函数调用前加上关键字 go 即可。

  2. Channels:Channels 是 Go 中提供的一种强大的并发同步机制。它可以在多个 Goroutine 之间传递数据并同步执行。你可以把它想象成一个 Goroutines 可以发送和接收值的管道。通过 make 函数创建 Channels,通过 <- 操作符发送和接收数据。

以下是一个简单的示例,展示了如何在 Go 中使用 Goroutines 和 Channels:

package main

import (
	"fmt"
	"time"
)

func say(s string, c chan string) {
    
	for i := 0; i < 5; i++ {
    
		time.Sleep(1 * time.Second)
		c <- s
	}
	close(c)
}

func main() {
    
	c := make(chan string)
	go say("Hello", c)
	for msg := range c {
    
		fmt.Println(msg)
	}
}

在这个示例中,我们创建了一个 Goroutine say,它每秒向 Channel c 发送一次 “Hello”,然后在 main 函数中,我们从 Channel c 中接收并打印这些消息。当 Channel c 被关闭并且没有更多的值可以接收时,range c 循环将结束。

GPT 给了一段示例代码,并且在最后给出了这段代码的解释,整体看来还是挺通俗易懂。接下来我想让 GPT 解释下 Goroutine 和“线程”的关系。我大概记得 Goroutine 是用户级线程,Go 的 runtime 自己管理和调度的,或者简单地叫做“协程”;而线程在这里指的是内核级线程,OS 完成的管理和调度。且看下 GPT 怎么说吧。

2.2 Goroutine 与线程

  • 我问 GPT:

Goroutines 和线程的关系是什么?Goroutines 调度和线程调度分别是什么原理?

  • GPT 说:

Goroutines 和线程的关系:

  • Goroutines 是 Go 语言中的并发体,它是一种轻量级的线程,由 Go 运行时(runtime)管理和调度,而不是由操作系统直接管理。
  • Goroutines 相比于操作系统的线程,其创建和销毁的开销更小,内存占用更少,可以轻松创建和管理上百万个 Goroutines。
  • 一个 Go 程序在运行时会有多个系统线程,每个系统线程在运行多个 Goroutine。Go 运行时会负责在这些系统线程上调度 Goroutines 的执行。

Goroutines 的调度:

  • Go 语言运行时包含了自己的调度器,这个调度器使用了 M:N 的调度模型,即 M 个 Goroutines 映射到 N 个系统线程上。
  • Go 调度器的工作方式和操作系统的调度器类似,但是在用户态完成调度,不需要切换到内核态,因此调度开销小。
  • Go 调度器使用了一种叫做分段式的抢却式调度策略,当一个 Goroutine 在执行时,会定期检查是否需要进行调度(例如,是否有更高优先级的 Goroutine 等待运行),这样可以保证 Goroutines 的公平调度。

线程的调度:

  • 线程的调度是由操作系统完成的,通常使用一种叫做抢占式的调度策略,当一个线程在执行时,操作系统会定期中断它,保存它的状态,然后选择另一个线程运行。
  • 线程的创建、销毁和切换都需要在内核态完成,因此开销比 Goroutines 大。
  • 线程可以利用多核处理器的并行计算能力,但是过多的线程会导致调度开销增大,影响程序的性能。

2.3 Goroutine 与线程的调度开销

  • 我问 GPT:

为什么线程调度的开销更大?

  • GPT 说:

线程调度的开销主要来自以下几个方面:

  1. 上下文切换:当操作系统决定停止运行一个线程并运行另一个线程时,它需要保存当前线程的状态(包括程序计数器,寄存器,内存映射等),然后加载另一个线程的状态。这个过程叫做上下文切换,它需要在用户态和内核态之间切换,这是一个相对耗时的操作。

  2. 内核态和用户态的切换:线程是由操作系统管理的,所以线程的创建、销毁和调度都需要在内核态完成。每次从用户态切换到内核态,都需要保存和恢复大量的状态信息,这也会增加额外的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值