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

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    解决golang sync.Wait()不执行的问题

    goroutine 似乎不用解释太多,可以利用它实现多线程,也可以利用它来实现异步事件。

    在使用关键字go的过程中,常常会将用到sync.WaitGroup,如下一段代码。

    package main
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    func Run() {
    	var wg = sync.WaitGroup{}
    	go func() {
    		wg.Add(1)
    		fmt.Println("halo world start")
    		time.Sleep(time.Second * 5)
    		fmt.Println("halo world end")
    		wg.Done()
    	}()
    	// time.Sleep(time.Millisecond * 5)
    	// fmt.Println("server will start")
    	wg.Wait()
    }
    func main() {
    	Run()
    }
    // output:
    // 
    

    期待的结果是打印 halo world start,5秒后打印halo world end,但是结果就是什么都没有,并且进程立即就结束了。

    原因

    关键字go是异步的,当执行到go,不会立即执行go 后面的内容,而且继续往下执行。此时wg.Add(1)还没有来得及执行,wg.Wait()就已经执行,即不会发生等待,进程就结束了。

    怎么解决:

    只需要在wg.Wait()前有其他操作,给与足够的时间让wg.Add(1)执行即可,

    方法一、时间等待,在wg.Wait()前加一句time.Sleep(time.Millisecond*5),既不影响性能,也能让wg.Add(1)来得及执行

    方法二、有IO操作,在wg.Wait()有其他IO操作,比如fmt.Println("server will start"),原因是std的输出会将进程从用户态转向内核态,打印命令发出后,又切回用户态,这个状态的转换是很有消耗的,wg.Add(1)也就有时间执行。

    Don't worry

    是否有存在担心,方法一的时间等待,等待的时候不够长,还是让wg.Add(1)来不及执行。don't worry.

    这里涉及到goroutine的调度问题,go进程在执行过程中,必须从goroutine队列中取出一个来执行,当wg.Wait()执行前就算执行time.Sleep(time.Nanosecond), 一纳秒,一…一…一纳秒,wg.Add(1)也来得及执行,因为主goroutine会被切换到睡眠状态,go进程必须要取一个线程来执行,就会取到wg.Add(1)这个线程,接下来就顺理成章了。

    同时方法二也是异曲同工,当发出打印的事件,整个进程都会被切换到就绪态,然后再被cpu执行。

    补充:【golang】sync.WaitGroup{}的wait()调用位置不同导致意想不到错误

    协程go多了,总觉的天下我有,没事就喜欢go一个协程,信手拈来,在项目中写个如下类似代码:

      wh := sync.WaitGroup{}
      out := make(chan string)
      go func() {
        wh.Wait()
        close(out)
      }()
      go func() {
        for i := 0; i  2; i++ {
          wh.Add(1)
          go tt(out)
          wh.Done()
        }
      }()

    想着开个协程去wait所有协程组,测试一下通了,没问题,好牛逼,协程呀!!

    可多测试即便就会出现:

    send close channel

    或者协程定死在某一个,还自已为是的认为自己写的子方法估计不小心关闭了channel,找了半天只找到在wg.wait()后进行了关闭。就这样扣了好久,还没想到自己画蛇添足的错误,经大佬一指点,原来开一个协程,还没等后一个协程进行wg.add(1)操作,wg.wait()就已经过了,关闭了channel。

    只好老老实实写:

      wh := sync.WaitGroup{}
      out := make(chan string)
      go func() {
        for i := 0; i  2; i++ {
          wh.Add(1)
          go tt(out)
          wh.Done()
        }
        wh.Wait()
        close(out)
      }()

    其实就是一个小小的同步问题,旁观者清呀!!!

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • Golang中的sync包的WaitGroup操作
    • Golang中的sync.WaitGroup用法实例
    • 深入Golang中的sync.Pool详解
    • golang中使用sync.Map的方法
    • golang中sync.Map并发创建、读取问题实战记录
    • 在golang中使用Sync.WaitGroup解决等待的问题
    上一篇:golang执行命令操作 exec.Command
    下一篇:Golang之defer 延迟调用操作
  • 相关文章
  • 

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

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

    解决golang sync.Wait()不执行的问题 解决,golang,sync.Wait,不执,