Go的进程阻塞

在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()
    原文作者:莫Y兮
    原文地址: https://www.jianshu.com/p/5911353366ee
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞