Go语言中如何实现协程同步

如果只有一个工作协程,需要主协程等待工作协程完成任务,可以使用通道来实现同步。

示例如下:

package main

import (
    "fmt"
    "time"
)

func worker(done chan bool) {
    fmt.Print("working...")
    // 忙一会..
    time.Sleep(time.Second)
    fmt.Println("done")

    // 通知主协程任务完成
    done <- true
}

func main() {

    // 创建非缓冲通道(ps:缓冲通道也可以完成这项任务)
    done := make(chan bool)
    go worker(done)

    // 阻塞等待worker协程任务完成
    <-done
}

不了解通道可以看这篇文章 Go语言的缓冲通道和非缓冲通道

如果需要等待有多个协程,一般有两种方式:使用缓冲通道、WaitGroup

1.使用缓冲通道阻塞等待所有协程的完成信息

示例如下:

package main

import (
	"fmt"
	"time"
)

func main() {
    // 创建布尔通道
	done := make(chan bool)

	for i := 0; i < 5; i++ {
		go func(done chan bool) {
			fmt.Println(i, "start working...")
			time.Sleep(2 * time.Second)
			fmt.Println(i, "finish working...")

            // 通知主协程任务完成
			done <- true
		}(done)
	}

    // 循环接收所有协程完成信息
	for i := 0; i < 5; i++ {
		<-done
	}
}
  1. 使用 WaitGroup

使用WaitGroup需要导入sync

示例如下:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
    // 声明 WaitGroup
	var wg sync.WaitGroup

	for i := 0; i < 5; i++ {
        // 递增 WaitGroup 的计数器。
		wg.Add(1)

        // 1.22版本前的GoLang需要添加下面语句避免所有闭包共享单一不变的变量,详见 https://go.dev/doc/faq#closures_and_goroutines
        // i := i

        // 以匿名函数形式运行协程
		go func(id int) {
			fmt.Println(id, "start working..")
            // 忙一会...
			time.Sleep(2 * time.Second)
			fmt.Println(id, "finish working..")

            // 在函数将要结束时,递减 WaitGroup 的计数器。
            // defer 会保证当函数返回时,执行紧跟 defer 的函数语句。
			defer wg.Done()
		}(i)
	}

    // 阻塞等待 WaitGroup 的计数器恢复为0,即所有协程工作完成。
	wg.Wait()
}

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值