我知道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
继续执行,并启动其他大猩猩worker
和sync
来完成它们的任务.在main
结束之前,我只是简单地添加了一个卧铺,以便为之前创建的Goroutines提供完成的时间.
我不是在问这个问题的其他解决方案,我只是想知道当createJobs
%发生在大猩猩之外的时候会发生什么.