Golang学习笔记-Goroutines

709 阅读3分钟

并发

首先 go 是一个实现并发的语言,并非并行

并发 vs 并行

并行是在同一时间内,可以同时执行多个任务;并发则是在一个时间片内只能执行单一任务,并把一段时间切分为多个时间片,不同时间片执行不同任务,在宏观上看像是在一段时间内同时执行了多个任务。如下图:

currency
并行不会总是导致更快的执行时间。这是因为并行运行的组件可能必须相互通信。在组件在多个内核中并行运行的情况下,此通信开销很高。因此,并行程序并不总是能够缩短执行时间

在golang 中使用 goroutines 和 channel 实现并发。

什么是 Goroutines

Goroutine是与其他函数或方法同时运行的函数或方法。可以认为它是轻量级的线程。与线程相比,创建Goroutine的成本很小。因此,Go应用程序具有成千上万个同时运行的Goroutine。

Goroutine 的优势

与线程相比,goroutines非常轻量。它们的堆栈大小只有几kb,并且堆栈可以根据应用程序的需要进行扩展和收缩,而对于线程,则必须指定堆栈大小并加以固定。

Goroutines在多路复用时会使用更少的OS线程。在具有数千个Goroutine的程序中,可能只有一个线程。如果该线程块中的任何Goroutine说正在等待用户输入,则将创建另一个OS线程,并将其余的Goroutine移至新的OS线程。作为程序员,我们从这些复杂的细节中抽象出来,并为它们提供了干净的API以进行并发工作。

Goroutine使用 channel 进行通信。通过设计通道,可以防止在使用Goroutines访问共享内存时发生争用情况。可以将 channel 视为与Goroutine进行通信的管道。

如何使用 Goroutine

在函数调用时,增加 go 关键字即可

import (  
    "fmt"
)

func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello()  // 开启一个新的 goroutine
    fmt.Println("main function")
}

main 函数中创建了一个 goroutine,此时执行 main 函数的线程则称为主goroutine(可以理解为父进程) 然而这段程序只输出main function,这是为什么呢,首先我们需要知道两条 goroutine的特性

  1. Goroutine 的调用时立刻返回的,并执行下一行代码。而且 Goroutine 的返回值将会被忽略
  2. 主Goroutine正在运行,其他任何Goroutine才能运行。如果主Goroutine终止,则程序将终止,并且其他Goroutine将不会运行。

在上述代码片中,主goroutine 开启 hello()后立刻打印 main function后退出,因此 hello()也并未执行完。可以在go hello() 后添加一行代码 time.Sleep(1 * time.Second)等待其完成(这样做只是为了理解 goroutine 机制,实际中需要使用 channel 来实现等待其他 goroutine 的执行)。

多 goroutine

我们使用下面的代码加深一下理解

import (  
    "fmt"
    "time"
)

func numbers() {  
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}
func alphabets() {  
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}
func main() {  
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}

上述代码的执行流程如图所示

goroutine

图像的第一部分蓝色代表数字Goroutine,栗色的第二部分代表字母Goroutine,绿色的第三部分代表主Goroutine,黑色的最后一部分将上述三个全部合并,并向我们展示了程序的执行时序。

如果喜欢,请关注我的公众号,或者查看我的博客 packyzbq.coding.me. 我会不定时的发送我自己的学习记录,大家互相学习交流哈~

weixin