我知道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)
    <-interrupt

}

func createJobs(jobs chan<- int) {
    defer close(jobs)
    for i := 1; i < 20; i++ {
        jobs <- i
    }
}

func worker(jobs <-chan int, processStarted <-chan struct{}, processCompleted <-chan struct{}) {

    for {
        select {
        case i := <-jobs:
            fmt.Printf("\nFetching job #%d from channel", i)
            time.Sleep(2 * time.Second)
        case <-processStarted:
            fmt.Print("\nProcess Started. Waiting for it to be completed")
            <-processCompleted
            fmt.Print("\nProcess completed")
        }

    }
}

func sync(processStarted chan<- struct{}, processCompleted chan<- struct{}) {

    // acquire semaphore. Send signal to channel to indicate that it is busy
    processStarted <- struct{}{}

    for i := 1; i < 5; i++ {
        fmt.Printf("\nprocessing %d", i)
        time.Sleep(5 * time.Second)
    }

    // release semaphore
    processCompleted <- struct{}{}
}

我try 测试的内容相当简单:我有一个createJobs函数,其唯一目的是向通道添加元素,在本例中为int通道.然后我得到了一个worker,它将从该通道中取出对象,并在取出下一个元素之前Hibernate 2秒钟.

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

在运行我的代码时,我收到以下错误:

致命错误:所有大猩猩都睡着了--死锁了!

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

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

那么我的代码就可以正确运行了.

我只是想知道为什么会发生这种事.我的意思是:main routine 正在执行,然后它命中对createJobs的调用(无回绕),所以main routine 应该被阻止,直到这个调用结束.一旦createJobs结束,就意味着通道中有元素.main继续执行,并启动其他大猩猩workersync来完成它们的任务.在main结束之前,我只是简单地添加了一个卧铺,以便为之前创建的Goroutines提供完成的时间.

我不是在问这个问题的其他解决方案,我只是想知道当createJobs%发生在大猩猩之外的时候会发生什么.

推荐答案

您正在将jobs声明为无缓冲通道,然后try 将20个值同步推送到其中.当您调用createJobs(jobs)时,这将阻塞您的Main函数.

将第13行更改为:

    jobs := make(chan int, 20)

...将打破僵局.

Go相关问答推荐

try 用GitHub操作中的release标签更新version. go文件,但失败了

消费者在NAT中是如何实现的

如何在使用中介资源时处理函数中的`defer`

禁用Golang中的终端

如何使用我的 struct 化日志(log)记录格式使人panic ?

如何在VSCode中为特定的.go文件创建调试配置?

Golang内置打印(Ln)函数&S行为怪异

当我有外键时,如何使用 GORM 创建数据库的新条目

Kperf 构建失败

如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf struct ?

最长连续重复的字符golang

Opensearch 错误 ping 弹性服务器:由未知权威签署的 x509 证书

Go泛型:无效的复合文字

Golang:如何判断通过缓冲通道进行通信时生产者或消费者是否较慢?

通过 golang 中的 gremlin-go 库嵌入 gremlin 服务器

有没有办法判断值是否满足接口中定义的类型约束?

Golang Echo Labstack 如何在模板视图中调用函数/方法

GORM GIN 更新查询导致 500 内部服务器错误

Go/Golang:如何从 big.Float 中提取最低有效数字?

手动下载并放置一个 golang mod 文件