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()
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,194评论 0 23
  • Goroutine是Go里的一种轻量级线程——协程。相对线程,协程的优势就在于它非常轻量级,进行上下文切换的代价非...
    witchiman阅读 4,949评论 0 9
  • 控制并发有三种种经典的方式,一种是通过channel通知实现并发控制 一种是WaitGroup,另外一种就是Con...
    wiseAaron阅读 10,746评论 4 34
  • Iterable MXNET中读入数据需要使用到数据迭代器(Iter),用户可以使用MXNET提供的一些数据迭代器...
    学而时习之_不亦说乎阅读 743评论 0 0
  • 给抽烟的前辈 领导 女生 给喝茶的前辈 领导 朋友
    陈稳阅读 111评论 0 0