美文网首页
Go的进程阻塞

Go的进程阻塞

作者: 莫Y兮 | 来源:发表于2018-03-21 23:38 被阅读746次

    在Go语言中,如果使用goroutine,经常需要阻塞主进程来等待goroutine的结束,我们有以下几种方式来实现


    使用channel实现

    package main
    
    import (
        "log"
        "time"
    )
    
    func main() {
        ch := make(chan int, 1)
    
        go func() {
            log.Println("wait 3s...")
            time.Sleep(3 * time.Second)
            ch<-1
        }()
    
        <-ch
    }
    

    使用waitGroup实现

    waiteGroup顾名思义,是等待一组行为执行结束,利用wg.Add()来添加group,利用wg.Donewg.Add(-1)来移除,wg.Wait()一直阻塞直到group完全释放

    package main
    
    import (
        "log"
        "sync"
        "time"
    )
    
    func main() {
        var wg sync.WaitGroup
    
        for i:=0;i<5;i++{
            wg.Add(1)
            go func(n int) {
                defer wg.Done()
                time.Sleep(3 * time.Second)
                log.Println(n)
            }(i)
        }
    
        wg.Wait()
    }
    

    NSQ源码中使用示例

    此处代码是NSQ中封装的WaitGroupWrapper,通过Wrap方法可以方便的添加需要执行的goroutine,并阻塞主进程

    package util
    
    import (
        "sync"
    )
    
    type WaitGroupWrapper struct {
        sync.WaitGroup
    }
    
    func (w *WaitGroupWrapper) Wrap(cb func()) {
        w.Add(1)
        go func() {
            cb()
            w.Done()
        }()
    }
    
    

    阻塞os信号

    如果进程被kill,很多时候我们不能立即退出,需要善后,处理类似内存信息持久化等信息。
    那么在Go中如何优雅的退出进程,下面这段代码通过捕捉os信号后,进行退出前的异常处理

        signalChan := make(chan os.Signal, 1)
        // 捕捉 Ctrl+c 和 kill 信号,写入signalChan
        signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
        // 此处执行处理逻辑
        nsqd.Main()
    
        // signalChan阻塞进程
        <-signalChan
    
        // 捕捉信号后在Exit函数中处理信息,例如内存持久化等信息防止丢失
        nsqd.Exit()
    

    相关文章

      网友评论

          本文标题:Go的进程阻塞

          本文链接:https://www.haomeiwen.com/subject/tkcoqftx.html