Go学习笔记 -- 并发原理
admin
2024-04-01 14:34:12
0

文章目录

    • Go 协程和普通线程对比
      • 内核级线程(线程)
        • 线程优点
        • 线程缺点
      • 用户级线程(协程)
        • 协程优点
        • 协程缺点
    • 调度器(GPM)
      • G\P\M 之间的工作关系
    • Go 使用协程
      • 创建协程
      • 注意

Go 协程和普通线程对比

       Go 拥有极强的并发编程能力,而 Go 并发编程强势原因,一部分原因是因为语法简单 ,还有一个更核心的原因是 Go 中协程 goroutine (用户态线程)的存在。
       在 Gogoroutine 是比普通线程(内核态线程)更加轻量化的存在。

内核级线程(线程)

       内核态线程简称线程,是在内核中维护了线程表进行跟踪监控的线程。是 CPU 调度和分派的基本单位,是具备进程某些属性,能够独立运行的更小单位,所以也称为轻量级进程。

       如果使用内核态线程在一个 CPU 上实现任务的并发,那么 CPU 会通过分配时间片的方式去执行任务,当正在运行的任务所分配的时间片用完了,就会切换到另一个任务,而在切换的之前会保存当前任务的状态(CPU寄存器、程序计数器中的内容),当下次再次切换到这个任务之前就会先加载之前保存到任务状态,这个过程称作上下文切换。

       而在上下文切换的过程该线程会从用户态转为内核态,加载时再由内核态转为用户态。而用户态和内核态切换的代价是很高的,从用户态到内核态的切换比较耗费资源的,而且内核资源是很珍贵的,所以内核态线程过多时,可能会出现内核资源耗尽的情况。

线程优点

  1. 多核 CPU 利用 :内核具有0级权限,因此可以在多个 CPU 上执行内核线程
  2. 操作系统级优化:线程之间是相对独立的,一个线程阻塞不会影响其他线程的执行。内核态线程在进行你 IO 操作时不需要进行系统调用 。

线程缺点

  1. 创建的时候需要切换到内核态,所以创建成本比较高。
  2. 切换的时候,需要用户态和内核态之间频繁的切换,切换成本较高。
  3. 线程数量有限制,当内核态线程过多时,会出现内核资源耗尽的情况。

用户级线程(协程)

       用户态线程简称协程,是完全由用户控制的线程,内核并不会感知到它的存在,用户级线程的创建、销毁、调度、状态变更以及其中的代码和数据都完全需要我们的程序自己去实现和处理。因为是存在在用户空间上的线程,所以在切换时不存在用户态和内核态的转换。

协程优点

  1. 不由内核管理,由用户自主管理,创建成本比较低。
  2. 不存在内核态和用户态的切换,切换成本比较低。
  3. 不需要操作系统去调度,所以可以跨操作系统,并且更加灵活、更容易控制。

协程缺点

  1. 因为操作系统的内核看不到协程,所以同属于一个进程的协程只能占有一个核,不能发挥多核优势。
  2. 操作系统不能主动调度协程,所以后面的协程只能等待前面的写成执行完才能获取到 CPU 资源。
  3. 同上,当前协程阻塞会导致后面的写成无法执行。
  4. 内核协作成本高,当要进行一些高权限的操作,比如读写文件时,需要频繁地进行用户态和内核态的切换。

调度器(GPM)

       GPMGo 语言运行时系统的重要组成部分
       其中 G 代表 goroutine 即协程,M 代表 machine 即系统线程、P 代表 Proccessor 代表写成和线程之间的联系

简单点理解就是:

G 是要被执行的任务实例
M 是实际的执行载体,需要绑定 P 成为一个执行单元才能调度 G
P 可以看作是任务处理器,P 中保存 M 执行 G 时的一些资源,P 决定了哪个 G 能配分配到哪个 M 上

G\P\M 之间的工作关系

       G 要调度到 M 上才能运行,M 需要关联 P 才可以执行 Go 代码,但当处理阻塞或系统调用中时,M 可以不用关联 P

       当进程启动时,会创建若干个(一般是内核数量)系统线程 M 和任务处理器 P,并一一绑定,因为一个线程对应一个 CPU 就不会出现上下文的切切换,能更大限度的节省资源。同时每一个任务处理器 P 都会对应一个私有的任务队列,但是私有队列有上限的,所以所有任务处理器还会有一个公用的全局队列。

       当有一个 G 被创建时,就会被放到一个任务处理器 P 的私有队列中等待被调度。如果所有的私有队列都满了,就会被放到全局队列中去。当 P 寻找 G 的时候,会先从自己的私有队列中寻找,如果没找到,再去全局队列中寻找,如果还是没有,它会去抢别的 P 中的 G。当任何地方都不能找到需要调度的 G 时,MP 则会断开连接。

       当 G 中进行了系统调用,则 M 也会进入系统调用状态,此时 P 会去寻找其他未在工作的 M 并为其寻找需要调度的任务。当 G 完成了系统调用,会进入空闲的私有队列或者全局队列,然后等待再次被调度。

       所以,GM 之间没有直接的联系,一个 G 可能被不同的 M 调度,一个 M 也可以调度不同的 G

Go 使用协程

创建协程

通过关键字 go 创建一个协程
一:普通函数创建

func goroutineTest(i int) {fmt.Println(i)
}
func main() {for i := 0; i < 10; i++ {go goroutineTest(i)}time.Sleep(time.Millisecond * 500)
}

二:匿名函数创建

func main() {for i := 0; i < 10; i++ {go func() {fmt.Println(i)}()}time.Sleep(time.Millisecond * 500)
}

三:匿名带参数函数创建

func main() {for i := 0; i < 10; i++ {go func(str string) {fmt.Println(str)}(fmt.Sprintf("%s%d", "s", i))}time.Sleep(time.Millisecond * 500)
}

注意

一:主协程不会等待子协程执行完毕
       以下列代码为例,一般来说控制台不会打印任何东西。原因是当代码运行到 go goroutineTest(i) 这一行时,并不是真正的会运行它,而是将它放到了任务队列中。所以可能子协程还没开始执行,主协程就已经退出了。所以我们可以再主协程加上等待。

func goroutineTest(i int) {fmt.Println(i)
}
func main() {for i := 0; i < 10; i++ {go goroutineTest(i)}time.Sleep(time.Millisecond * 500)
}

二:协程的执行没有顺序
       同上,当写成创建是,并不是立即执行,而是被分到不同的队列中等待被调度,而调度是不能保证先后顺序的(只能保证同一个队列中的任务先进先出),因此上述代码打印出来的结果大部分情况下时乱序的。
三:无参匿名函数中的变量变化

func main() {for i := 0; i < 3; i++ {go func() {fmt.Println(i)}()}time.Sleep(time.Millisecond * 500)
}

这段代码的打印结果如下:

2
2
3

       因为匿名函数不携带参数信息,只有匿名方法执行到 fmt.Println(i) 这一行时才会去读取 i 的值。又因为协程执行是有延迟的,所以当执行到这一句时, i 的值可能已经发生了变化。

下一篇再研究主协程等待子协程执行完毕以及确保子协程执行顺序的方法…

相关内容

热门资讯

安卓系统过生日软件手机,手机一... 你知道吗?安卓系统最近过生日了!是的,你没听错,那个陪伴我们多年的安卓系统,已经迎来了它的第13个生...
安卓系统角标怎么去掉,Andr... 手机里的安卓系统角标总是跳来跳去,是不是让你觉得有点烦?别急,今天就来手把手教你如何把这些小家伙给“...
安卓系统am指令详解,Andr... 你有没有想过,你的安卓手机里那些神奇的指令其实就像是一把钥匙,能解锁手机里的各种秘密功能呢?今天,就...
单反安卓系统安装教程,玩转摄影... 你有没有想过,把安卓系统装在你的单反相机上,是不是能让你拍照的时候更加得心应手呢?想象你可以在相机上...
都有什么安卓电脑系统,无限可能 你有没有想过,你的安卓手机里的系统,其实也可以用在电脑上呢?没错,就是那个你每天刷刷刷的安卓系统,现...
华为能进系统账户吗安卓,揭秘系... 你有没有想过,手机里的那些秘密,是不是只有你自己才能解锁呢?今天,咱们就来聊聊这个话题——华为手机,...
安卓改系统版本号,版本号背后的... 你有没有想过,你的安卓手机系统版本号其实可以改一改呢?没错,就是那个看起来平平无奇、却可能隐藏着无限...
安卓系统吃鸡类游戏,安卓平台吃... 你有没有发现,最近手机上的一款游戏火得一塌糊涂?没错,就是安卓系统上的吃鸡类游戏!这款游戏不仅让无数...
模拟器安卓系统10.0,模拟器... 你有没有想过,在手机上玩电脑游戏的感觉?那种大屏幕、高配置的体验,是不是让你心动不已?现在,有了安卓...
安卓平板系统比较稳定,打造流畅... 你有没有发现,现在市面上平板电脑的种类真是五花八门,让人挑花了眼。不过,说到稳定性,安卓平板系统可是...
安卓系统的xsmax,性能与体... 你有没有发现,最近安卓系统里的xsmax可是火得一塌糊涂啊!这款手机不仅外观时尚,性能强大,而且性价...
安卓4.04系统的微信,探索微... 你有没有发现,用安卓4.04系统的手机微信,有时候会有一些特别的小秘密呢?今天,就让我带你一探究竟,...
2k23安卓系统,创新功能与卓... 你有没有发现,最近你的手机是不是变得更快了?没错,我要说的就是那个让无数安卓用户翘首以盼的2k23安...
安卓更换国外系统怎么换,安卓设... 你有没有想过给你的安卓手机换换口味,体验一下国外的操作系统呢?没错,就是那种让你仿佛置身异国他乡的感...
怎样备份手机安卓系统,安卓手机... 手机里的照片、视频、联系人,这些都是我们珍贵的回忆和重要信息,万一手机出了问题,岂不是要心疼死?别担...
安卓系统怎么找优盘文件,安卓系... 你有没有遇到过这种情况:手机里突然多了一个陌生的优盘文件,但你就是找不到它在安卓系统里的具体位置?别...
安卓联想建模系统怎么用,安卓平... 你有没有想过,手机里的那些神奇功能是怎么来的呢?其实,这背后可是有高科技支持的哦!今天,就让我来带你...
安卓系统充电电流修改,揭秘充电... 你有没有想过,你的安卓手机充电速度有时候慢得让人抓狂?别急,今天就来给你揭秘如何巧妙地修改安卓系统的...
海尔安卓系统电视进不去,海尔安... 最近是不是你也遇到了这样的烦恼:家里的海尔安卓系统电视突然就进不去啦?别急,让我来给你详细说说这个问...
为什么不弃用安卓系统,坚守阵地... 你知道吗?在这个科技飞速发展的时代,手机操作系统可是咱们日常生活中不可或缺的一部分。说到手机系统,安...