• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Go 并发实现协程同步的多种解决方法

    go 简洁的并发

    多核处理器越来越普及。有没有一种简单的办法,能够让我们写的软件释放多核的威力?是有的。随着Golang, Erlang, Scala等为并发设计的程序语言的兴起,新的并发模式逐渐清晰。正如过程式编程和面向对象一样,一个好的编程模式有一个极其简洁的内核,还有在此之上丰富的外延。可以解决现实世界中各种各样的问题。本文以GO语言为例,解释其中内核、外延。

    前言

    Java 中有一系列的线程同步的方法,go 里面有 goroutine(协程),先看下下面的代码执行的结果是什么呢?

     package main
     import (
       "fmt"
    )
     func main() {
      go func() {
        fmt.Println("Goroutine 1")
      }()
      go func() {
        fmt.Println("Goroutine 2")
      }()
    }

    执行以上代码很可能看不到输出。

    因为有可能这两个协程还没得到执行,主协程就已经结束了,而主协程结束时会结束所有其他协程,所以导致代码运行的结果什么都没有。

    估计不少新接触 go 的童鞋都会对此郁闷😒,可能会问那么该如何等待主协程中创建的协程执行完毕之后再结束主协程呢?

    下面说几种可以解决的方法:

    Sleep 一段时间

    在 main 方法退出之前 sleep 一段时间就可能会出现结果了,如下代码:

     package main
     import (
       "fmt"
      "time"
     )
     func main() {
       go func() {
        fmt.Println("Goroutine 1")
      }()
      go func() {
        fmt.Println("Goroutine 2")
      }()
      time.Sleep(time.Second * 1) // 睡眠1秒,等待上面两个协程结束
    }

    这两个简单的协程执行消耗的时间很短的,所以你会发现现在就有结果出现了。

    Goroutine 1
    Goroutine 2

    为什么上面我要说 “可能会出现” ?

    因为 sleep 这个时间目前是设置的 1s,如果我这两个协程里面执行了很复杂的逻辑操作(时间大于 1s),那么就会发现依旧也是无结果打印出来的。

    那么就可以发现这种方式得到问题所在了:我们无法确定需要睡眠多久

    上面那种方式有问题,go 里面其实也可以用管道来实现同步的。

    管道实现同步

    那么用管道怎么实现同步呢?show code:

     package main
     import (
       "fmt"
     )
     func main() {
       ch := make(chan struct{})
      count := 2 // count 表示活动的协程个数
      go func() {
        fmt.Println("Goroutine 1")
        ch - struct{}{} // 协程结束,发出信号
      }()
      go func() {
        fmt.Println("Goroutine 2")
        ch - struct{}{} // 协程结束,发出信号
      }()
      for range ch {
        // 每次从ch中接收数据,表明一个活动的协程结束
        count--
        // 当所有活动的协程都结束时,关闭管道
        if count == 0 {
          close(ch)
        }
      }
    }
    
    

    这种方式是一种比较完美的解决方案, goroutine / channel 它们也是在 go 里面经常搭配在一起的一对。

    sync.WaitGroup

    其实 go 里面也提供了更简单的方式 —— 使用 sync.WaitGroup。

    WaitGroup 顾名思义,就是用来等待一组操作完成的。WaitGroup 内部实现了一个计数器,用来记录未完成的操作个数,它提供了三个方法:

    继续 show code:

    package main
     import (
       "fmt"
      "sync"
     )
     func main() {
      var wg sync.WaitGroup
      wg.Add(2) // 因为有两个动作,所以增加2个计数
      go func() {
        fmt.Println("Goroutine 1")
        wg.Done() // 操作完成,减少一个计数
      }()
      go func() {
        fmt.Println("Goroutine 2")
        wg.Done() // 操作完成,减少一个计数
      }()
      wg.Wait() // 等待,直到计数为0
    }

    你会发现也是可以看到运行结果的,是不是发现这种方式是很简单的。

    总结

    以上所述是小编给大家介绍的Go 并发实现协程同步的多种解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

    您可能感兴趣的文章:
    • go等待一组协程结束的操作方式
    • golang协程池模拟实现群发邮件功能
    • 解决go在函数退出后子协程的退出问题
    • Go使用协程交替打印字符
    • Golang 之协程的用法讲解
    • go 协程返回值处理操作
    • 浅谈golang for 循环中使用协程的问题
    • Go并发:使用sync.WaitGroup实现协程同步方式
    上一篇:浅谈Go Channel 高级实践
    下一篇:基于golang如何实现error工具包详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Go 并发实现协程同步的多种解决方法 并发,实现,协程,同步,的,