go 协程

作者 : admin 本文共1256个字,预计阅读时间需要4分钟 发布时间: 2024-06-17 共1人阅读

协程又称为微线程,作用:在执行A函数的时候,可以随时中断,去执行B函数,然后中断继续执行A函数(可以自动切换),注意这一切换过程并不是函数调用(没有调用语句),过程很像多线程,然而协程中只有一个线程在执行(协程的本质是单线程)。线程是CUP控制的,而协程是程序自身控制的,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级。

协程执行流程

go 协程插图

 主死从随(主线程执行完成了,从线程就被停止执行)

下面看列子:

package main

import (
	"fmt"
	"time"
)

// 启动多个协程
func main() { //主线程
	//匿名函数+外部变量=闭包
	for i := 1; i <= 5; i++ {
		//启动一个协程,使用匿名函数,直接使用函数
		go func(n int) {
			fmt.Println(n)
		}(i)
	}

	//主线程不加等待时间,可能协程没有执行,主线程就结束了,但是有个问题,你怎么知道多久的时间可以结束掉协程呢??如何进行优雅的等待?
	time.Sleep(time.Second * 2)
}

如何优雅的等待协程执行完成?

WaitGroup引入

【1】WaitGroup的作用:
WaitGroup用于等待一组线程的结束。父线程调用Add方法来设定应等待的线程的数量。每个被等待的线程在结束时应调用Done方法。同时,主线程里可以调用Wait方法阻塞至所有线程结束。—》解决主线程在子协程结束后自动结束

【2】主要函数:
(1)func(*WaitGroup)Add

func (wg *WaitGroup) Add(delta int)

Add方法向内部计数加上delta,delta可以是负数;如果内部计算器变为0,Wait方法阻塞等待的所有线程都会释放,如果计数器小于0,方法panic。注意Add加上正数的调用应在Wait之前,否则Wait可能只会等待很少的线程。一般来说方法应在创建新的线程或者其他应等待的事件之前调用。

(2)func(*WaitGroup) Done()

func(wg *WaitGroup) Done()

done方法减少WaitGroup计数器的值,应在线程的最后执行。

(3)func(*WaitGroup) Wait

funt(wg *WaitGroup) Wait()

Wait方法阻塞直到WaitGroup计数器减为0.

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup //只定义,无需赋值

func main() {
	//wg.Add(5) //可以在最开始知道协程次数的情况下先Add操作,注意:Add中加入的数字和协程的次数一定要保持一致,否则会出错
	//启动5个协程
	for i := 1; i <= 5; i++ {
		wg.Add(1) //协程开始的时候加1操作
		go func(n int) {
			defer wg.Done() //协程完成的时候减1操作(如果忘记计数器减1操作,就结合defer关键字使用)
			fmt.Println(n)
		}(i)
	}

	wg.Wait() //主线程一直在阻塞,什么时候wg减为0了,就停止阻塞
}

 

本站无任何商业行为
个人在线分享 » go 协程
E-->