ZBLOG

import ( "fmt" "sync" ) func main() { n := 5 channelS := make([]chan struct{}, n) for i := 0; i < n; i++ { channelS[i] = make(chan struct{}) } wg := sync.WaitGroup{} wg.Add(n) global := 0 for i := 0; i < n; i++ { go func() { defe...

在您提供的代码中,确实会导致死锁。让我们逐步分析一下原因。

原因分析

  1. 全局变量 global 的并发访问global 是一个共享变量,在多个 goroutine 中被同时读取和写入,而没有进行同步控制。这可能导致数据竞争,并且不保证在所有 goroutine 中都能正确更新 global 的值。

  2. 通道操作的顺序问题:每个 goroutine 在尝试从其相应的 channel (channelS[global]) 中读取之前,需要等待其他 goroutine 完成自己的工作。但是,由于没有适当地处理 global 的更新,某些 goroutine 可能会永远阻塞。例如,如果 global 达到 n(例如 5),它将尝试访问 channelS[5],但该索引超出了切片的范围,从而引发错误。

  3. 启动顺序不当:程序逻辑是通过 channelS[0] <- struct{}{} 开始第一个 goroutine,但因为没有确保其他 goroutine 能够按照正确的顺序执行,所以可能会出现死锁。

修改建议

为了避免这些问题,可以使用如下修改:

  1. 使用互斥锁来保护对 global 变量的访问。
  2. 确保不会越界访问 channel 切片。
  3. 确保每个协程可以在合适的时候退出,不至于造成死锁。

以下是经过修改后的示例代码:

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. func main() {
  7. n := 5
  8. channelS := make([]chan struct{}, n)
  9. for i := 0; i < n; i++ {
  10. channelS[i] = make(chan struct{})
  11. }
  12. var wg sync.WaitGroup
  13. wg.Add(n)
  14. global := 0
  15. var mu sync.Mutex // 创建互斥锁
  16. for i := 0; i < n; i++ {
  17. go func(i int) {
  18. defer wg.Done()
  19. if i == 0 {
  20. channelS[0] <- struct{}{} // 启动第一个通道
  21. }
  22. <-channelS[i]
  23. mu.Lock() // 加锁以安全地读取和写入 global
  24. fmt.Println(i) // 打印当前索引而不是 global
  25. global++
  26. if global < n { // 确保不会越界
  27. channelS[global] <- struct{}{}
  28. }
  29. mu.Unlock() // 解锁
  30. }(i)
  31. }
  32. wg.Wait()
  33. }

更正后的关键点

  • 使用了一个互斥锁 (sync.Mutex) 来保护对 global 的访问,确保它在线程间安全。
  • 修改了打印逻辑,以便每个线程能够打印自己的索引而不是使用共享变量。
  • 添加了条件检查,以确保不会尝试发送到超出通道范围的索引。


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

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?