Post

记录工作中发现的任务队列的死锁问题

go的并发理念是所有共享内存的访问修改的任务都推送到通道中串行修改,而不是使用锁去保护共享资源。这样的设计理念,使得在并发运算的过程中保证资源的无锁串行访问,提高程序效率。

但是无锁意味着不存在死锁情况吗?我以前是这么认为的,知道在最近的工作上,才遇见这样的问题。我们知道就算是chan,当其中的消息满的时候,此时再往chan中推送消息,推送消息方协程会被阻塞。

假设这样的场景:现在有多个并发协程进行运算,同时向同一个chan中发送任务,这个chan的最大缓冲区是2个消息。chan中取出一个消息开始执行,此时chan又到来一个消息,然后上一个取出的任务中又往chan中塞入一个消息,但是发现塞不进去阻塞了。这样便造成了死锁,chan无法再取出消息,因为当前任务没有执行完毕。但任务无法退出因为无法向chan中发送消息。

我惊奇的发现,在缓冲区较少的情况下,这样的问题的触发概率非常的大。

那有什么解决方案吗?

第一个就是规范写法,推送往chan的任务代码中不能接着往chan写入。但这是不现实的,有些需求的到来我们无法避免;第二个就是把chan的输入任务和输出任务分离开,使用两个chan来执行这一过程。

This post is licensed under CC BY 4.0 by the author.