Go并发:Goroutine

1.并发基础概念:进程、线程、协程

(1) 进程

可以比作食材加工的一系列动作

进程就是程序在操作系统中的一次执行过程,是由系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间。一个进程至少有5种基本状态:初始态、执行态、等待状态、就绪状态、终止状态。

通俗讲: 进程就是一个正在执行的程序。

[一般情况] 一个程序一个进程

[多进程]] 一个程序多个进程

可以在终端输入以下内容,来列出所有的进程

ps -A

比如在Windows系统中,一个运行的xx.exe就是一个进程。

(2) 线程

可以比作食材加工的某一个动作

线程是运算调度的最小单元,是进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。

进程与线程的区别如下

根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

查看线程

进入 terminal输入命令 ps-M[pid]查看对应 pid 线程

(3) 协程

协程(goroutine) 是轻量级的执行线程。

实操

假设我们有一个函数叫做 action()。 我们一般会这样 同步地 调用它使用 go action() 在一个协程中调用这个函数。 这个新的 Go 协程将会 并发地 执行这个函数。

package main

import (

"fmt"

// "time"

)

func action() {

fmt.Println("Test Goroutine")

}

func main() {

go action()

// time.Sleep(2 * time.Second)

}

可见咩有任何输出,把注释内容取消注释再运行

为什么要沉睡?

go 语言运行非常快,若没有沉睡,可能会导致

“协程还没有执行完, main 函数已经结束了”

最终导致协程结束前, main 函数已经被销毁

因此我们需要让主进程去等待一定时间的子协程,才能得到子协程的输出

2.多协程核心机理

步骤

任务切片/分配启动多个协程合并多个协程结果

使用场景

运算量比较多协程间依赖性比较弱

3.多协程等待实操

我们可以使用通道来同步协程之间的执行状态。使用 wait group 等待多个协程完成

package main

import (

"fmt"

"sync"

)

func main() {

var wg sync.WaitGroup

for i := 0; i < 2; i ++ {

wg.Add(1)

go func(num int) {

fmt.Printf("Goroutine Test %d\n", num)

wg.Done()

}(i)

}

wg.Wait()

}

更多细节清查阅 waitgroup

Go by Example 中文版: WaitGroup (gobyexample-cn.github.io)

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: