当填充通道的函数调用未嵌入 Goroutine 中时,为什么会出现死锁?

当填充通道的函数调用未嵌入 goroutine 中时,为什么会出现死锁?

当填充通道的函数调用未嵌入Goroutine中时,会出现死锁的原因是因为通道的发送和接收操作是阻塞的。如果在主Goroutine中调用填充通道的函数,并且该函数内部没有将填充操作放入新的Goroutine中运行,那么主Goroutine会一直等待通道有足够的空间来接收数据,而填充操作又无法进行,从而导致死锁的产生。因此,为了避免死锁,我们需要在填充通道的操作中使用Goroutine来进行并发执行,以确保填充操作和接收操作可以同时进行。

问题内容

我知道 sync 包及其 waitgroup 选项,我不想将其用于此测试。我正在测试一种信号量。

所以我有:

package main

import (
“fmt”
“os”
“time”
)

func main() {

fmt.print(“wassap”)

jobs := make(chan int)
processstarted := make(chan struct{}, 1)
processcompleted := make(chan struct{}, 1)

createjobs(jobs)

go func() {
worker(jobs, processstarted, processcompleted)
}()

go func() {
sync(processstarted, processcompleted)
}()

time.sleep(3600 * time.second)
fmt.print(“nend of main…”)

interrupt := make(chan os.signal)
登录后复制

我想要测试的非常简单:我有一个 createjobs 函数,其唯一目的是将元素添加到通道,在本例中是一个 int 通道。然后我有一个 worker 将从该通道中提取对象并在提取下一个元素之前休眠 2 秒。

现在,还有同步功能。该函数的唯一目的是模拟 worker 运行时启动的进程。如果此进程处于活动状态,则在 sync 结束时应停止处理 jobs 元素,这就是为什么我有两个通道,一个表示进程已启动,另一个表示进程结束。

运行我的代码时出现以下错误:

fatal error: all goroutines are asleep – deadlock!

登录后复制

如果我修改 createjobs 的调用方式,将其包装在如下所示的 goroutine 中:

go func() {
createJobs(jobs)
}()

登录后复制

然后我的代码运行正确。

我只是想了解为什么会发生这种情况。我的意思是: main 例程正在执行,然后它调用 createjobs (无换行),因此 main 例程应该被阻止,直到此调用结束。一旦 createjobs 结束,就说明通道中有元素了。 main 继续执行并启动其他 goroutine worker 和 sync 来完成它们的工作。在 main 结束之前,我只是添加一个睡眠程序,以便为之前创建的 goroutine 提供完成时间。

我不是在询问这个问题的其他解决方案,我只是想知道当 createjobs 发生在 goroutine 之外时会发生什么。

解决方法

您将 jobs 声明为无缓冲通道,然后尝试将 20 个值同步推入其中。当您调用 createjobs(jobs) 时,这将阻止您的主函数。

将第 13 行更改为:

jobs := make(chan int, 20)

登录后复制

…将解决僵局。

编辑 – 评论中要求的澄清:

无缓冲通道没有容量,并且会阻止生产者的执行,直到消费者收到消息为止。

无缓冲通道的一个很好的类比是管道,在本例中,过程如下所示:

+——————+ +————+ +————-+
| PRODUCER | | PIPE | | CONSUMER |
| +—->| +—–>| |
| createJobs(jobs) | | unbuffered | | worker(…) |
| | | channel | | |
+——————+ +————+ +————-+

登录后复制

发生死锁是因为 createjobs(jobs) 被同步调用,并且还没有消费者在运行。

当在 goroutine 中调用函数(producer)时它可以工作,因为基本上插入通道和读取通道是并行发生的?

是的。如果生产者被异步调用,它不会阻塞 main() 函数,因此消费者也将有机会被调用。在这种情况下,生产者将一一推送其所有任务,就像工作人员一一消费它们一样。

以上就是当填充通道的函数调用未嵌入 Goroutine 中时,为什么会出现死锁?的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

上一篇 golang json'true'不是True?
下一篇 在 Go 中发出 HTTP GET 请求时出错:“dial tcp:lookup api.ipify.org on:53:read udp:50975>:53:read:connectionrejected”