当前位置: 首页 > 网络应用技术

Golang频道的三个主要坑,您是否踩了它?

时间:2023-03-07 18:36:53 网络应用技术

  你好!本文是“ Golang并发编程”系列的第三篇文章?

  在上一篇文章中,我们了解了渠道的基本用法。不熟悉的朋友可以先阅读上一篇文章。

  当使用频道在Goroutine之间进行通信时,有时场景会变得非常复杂,因此偶尔难以检测并且无法定位的虫子(例如服务和OOM)。

  在本文中,我们可以清理通道中常用的三个常见坑:恐慌,死锁和内存泄漏,以防止问题发生之前。

  汇编时,GO语言新手很容易遇到此僵局的问题:

  这是我喜欢看到的“死锁” ...在操作系统中,我们了解到“死锁”是两个彼此等待的线程,它们被消耗了,并且过程必须结束。Dead Lock“ Go语言也相似。两个goroutine互相等待,导致该程序在那里消费并无法继续运行。在阅读很多死亡锁时,可以将渠道引起的死锁汇总为以下类型的案例(未封闭的渠道的情况第一的):

  渠道的生产商和消费者必须成对出现。如果缺少一个人,它将导致死锁,例如:

  或者:

  除了需要出现之外,它还需要出现在不同的goroutine中,例如::::

  用于缓冲频道:

  缓冲通道将把接收到的元素放在首位,然后将发生阻塞。发生阻塞时,如果主要goroutine被阻止,将会出现僵局

  因此,在实际使用中,建议尽可能多地使用缓冲通道。

  通常在发布过程中的警报或观察记忆中发现内存泄漏。服务记忆通常会缓慢上升,直到系统OOM在空中丢失为止。

  在GO语言中,错误使用通道可能会导致Goroutine泄漏,从而导致内存泄漏。

  无法修复错误,我不会写错误?goroutine泄漏的核心是:

  生产者/消费者所在的Goroutine已退出,相应的消费者/生产者的Goroutine将始终阻止它,直到流程退出流程

  我们通常使用频道执行一些超时控件,例如,以下示例:

  在这里,我们使用Goroutine模拟IO操作,以及模拟客户端处理逻辑的主要Goroutine。

  如果这是在服务器代码中,则处理此请求后,它将被悬挂和泄漏,只需等待OOM =。=。

  如果生产者不继续生产,则消费者所在的Goroutine也将阻止并且不会退出:例如:

  在这种情况下,您只需要增加操作即可。收到关闭信号后,将退出操作。Goroutine将不再被阻止,可以回收。

  防止Goroutine泄漏的核心是:

  创建Goroutine时,您必须弄清楚何时回收

  特定于执行级别,包括:

  恐慌更加令人兴奋。通常,在测试期间找不到。偶尔在发布后,该程序被挂起,并且在服务发生后触发警报。渠道引起的恐慌通常是以下原因:

  让我们首先给一个简单的栗子:

  在实际开发过程中,在处理多个Goroutine合作时,可能会有一个具有频道的Goroutine。另一个不知道。如果您进入结束,例如,您将删除:

  所有弊端的来源是在Go语言中。您不知道是否闭合了频道,因此在尝试进行近距离操作时,您应该准备好慌张...

  与上述相同,在尝试在频道中发送数据时,您应该考虑

  当我第一次遇到上面提到的恐慌问题时,我还试图找到一个内置的功能来检查闭合状态。结果,我发现没有这样的功能...

  因此,如果有这样的功能,它真的可以解决恐慌问题吗?答案不是。因为频道是在并发环境中的收发器操作,即使当前结果是错误的,它仍然无法直接进行。例如,以下代码:以下代码:

  遵循较少的原则是更多,此功能还不够

  结论:除非您必须关闭Chan。

  当Chan没有发件人和接收器时,它不再使用,GC会在一段时间后标记和清理此陈通知机制,尤其是当生产者和消费者之间的关系为1:m时,通过近距离告诉下游:我已经完成工作,不要读它。

  Chan的原则关闭了:

  只要我们遵循这两个原则,我们就可以避免两个恐慌场景,即:将数据发送到封闭的陈或关闭封闭的陈。

  根据生产者与消费者之间的关系,可以将其分解为以下类别:

  这种情况来自参考材料中的“如何优雅关闭渠道”。GO 101系列非常好。推荐阅读?

  待续 ...

  原始:https://juejin.cn/post/7100597828359028750