• Golang如何优雅的关闭channel?


    如何优雅的关闭channel?

    channel关闭原则

    "如何优雅的关闭channel?",这种问题经常在面试题中出现,究其原因,是因为channel创建容易,但是关闭"不易",原因有以下三点:

    • 关闭时机未知,在不改变channel自身状态的条件下,无法知道他是否已经关闭
    • 不能无脑关闭,如果一个channel已经关闭,重复关闭channel会导致panic
    • 往一个关闭的channel写数据,也会导致panic

    根据上面的三个不易,可以整理出三条channel的关闭原则:

    • 不要在消费者端关闭channel
    • 不要在有多个并行的生产者时关闭channel
    • 应该只在唯一或者最后一个生产者协程中关闭channel

    简单解释一下这三个原则:

    • 第一个原则,消费者不知道不知道channel何时该关闭,如果关闭了已经关闭的channel,会导致panic,而且分布式应用通常有多个消费者,每个消费者的行为一致,这么多消费者都尝试关闭channel必然会导致panic
    • 第二个原则,如果有多个生产者往channel中写数据,如果一个生产者关闭了channel,其他生产者还在往channel里写,必然会导致panic
    • 第三个原则,只要坚持这个原则,就可以确保向已经关闭的channel中发送数据的情况不会发生

    "邪门歪道"式关闭channel

    • defer+recover
    • sys.Once,确保只会关闭一次
    • sys.Mutex,确保只会关闭一次

    优雅的关闭channel

    根据生产者和消费者的数量关系,总共可以分为四种情况:

    • 单生产者,单消费者
    • 单生产者,多消费者
    • 多生产者,单消费者
    • 多生产者,多消费者

    下面我们逐个分析这四种情况,应该如果优雅关闭channle

    情况1:单生产者,单消费者

    • 直接让生产者关闭channel即可

    情况2:单生产者,多消费者

    • 同样直接让生产者关闭channel即可

    情况三:多生产者,单消费者

    1.生产者会主动退出情况

    主动退出:生产者执行完循环,主动退出goroutine

    • 等生产者都发送完后在另外一个goroutine中关闭channel,可利用sync.WaitGroup通知关闭另外goroutine关闭channel,也可利用额外的channle
    • 不可以直接在生产者中关闭channle,因为生产者有多个,贸然关闭会导致某个生产者向channle中发送数据,导致panic

    2.生产者不会主动退出情况

    • 消费者通过一个额外的channle来通知生产者停止生产数据,但数据channel没有被任何goroutine持有时,GC会帮我们关闭channel并回收

    情况四,多生产者,多消费者

    1.生产者会主动退出情况

    • 同样等生产者都发送完后在另外一个goroutine中关闭channle,可利用sync.WaitGroup或额外channel

    2.生产者不会主动退出情况,消费者会主动退出情况

    • 等消费者都退出之后,通知生产者停止生产数据,等待数据channel不被任何goroutine持有时,GC会帮我们关闭channel并回收

    3.生产者不会主动退出情况,消费者不会主动退出情况

    • 针对这种生产者和消费者都不主动退出的情况,我们应该想办法让消费者退出,比如说让消费者监听一个退出信号,有退出信号时就退出,然后就可以演变成消费者会退出的情况进行处理了

    总结

    • 任何时候都不应该违反channel的关闭原则,如果你违反了,建议重新设计一下程序,或者思考一下,是不是该重构了
    心之所向,素履以往
  • 相关阅读:
    day67——前后端传输数据的编码格式、ajax传json数据/传文件、批量插入
    day66——choices参数、MTV/MVC模型、三种创建多对多的方式、AJAX
    day65——聚合函数、分组查询、F与Q查询、django开事务、orm查询优化
    dayⅢ、基本数据类型+运算符作业
    dayⅡ:编程语言+变量+垃圾回收制
    dayⅡ:变量作业
    dayⅠ:计算机基础知识
    ⅩⅥ:无参装饰器
    ⅩⅤ:作业
    ⅩⅤ:名称空间与作用域
  • 原文地址:https://www.cnblogs.com/yinbiao/p/15770272.html
Copyright © 2020-2023  润新知