ZBLOG

package main import ( "fmt" "sync" "time" ) func main() { chaS := make([]chan struct{}, 10) for i := 0; i < len(chaS); i++ { chaS[i] = make(chan struct{}) } var global = 1 wg := sync.WaitGroup{} for i := 0; i < 10; i++ { <-chaS[i] ...

在你的代码中,死锁的原因主要有以下几点:

  1. 通道的同步问题:你在 for 循环中使用 <-chaS[i] 来接收通道中的信号,这意味着每个 goroutine 都会等待前一个 goroutine 的信号。然而,在你的 goroutine 内部又向 chaS[(i+1)/10] 发送了一个信号,该计算方式 (i+1)/10 对于 i=0i=9 的情况来说,总是会得到 0,从而使得在最后一次迭代后试图发送到 chaS[1],这可能导致未初始化的 channel 被写入,最终造成死锁。

  2. 并发控制不当:当你调用 <-chaS[i] 时,它阻塞等待直到有数据可读,而在 goroutine 中发送信号的逻辑可能不会被触发。此时,主循环没有正确地处理 goroutines 启动顺序,使得它们无法相互激活,从而导致死锁。

  3. 不一致的索引:对于通道数组,你使用的是整除来确定下一个通道的索引 (i + 1) / 10,这显然是不符合需求的,因为在大多数情况下都无法正确地引用到下一个通道索引。

下面是修复后的版本,可以帮助你避免这种死锁情况:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	chaS := make([]chan struct{}, 10)
	for i := range chaS {
		chaS[i] = make(chan struct{}) // 初始化每个通道
	}

	var global = 1
	wg := sync.WaitGroup{}

	wg.Add(10) // 提前设置待完成任务数

	for i := 0; i < len(chaS); i++ {
		go func(i int) {
			defer wg.Done()
			if i > 0 {
				<-chaS[i-1] // 等待前一个 channel 信号
			}
			fmt.Println(global)
			time.Sleep(time.Second)
			global++
			if i < len(chaS)-1 {
				chaS[i] <- struct{}{} // 向下一个 channel 发送信号
			}
		}(i)
	}

	// 开始第一个 goroutine
	chaS[0] <- struct{}{}

	wg.Wait() // 等待所有 goroutines 完成
}

修复要点:

  • 在每个 goroutine 中,我们检查是否存在前一个索引并进行接收,这样可以保证只有当前面结束时才继续。
  • 使用增加全局 WaitGroup 的数量来确保我们等待所有协程完成。
  • 修正了对下一个通道的引用逻辑,只需在确保不越界后进行发送。

这个修改确保了程序按照期望的顺序执行,并消除了潜在的死锁问题。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20257

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?