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. 确保每个协程可以在合适的时候退出,不至于造成死锁。

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

package main

import (
	"fmt"
	"sync"
)

func main() {
	n := 5
	channelS := make([]chan struct{}, n)
	for i := 0; i < n; i++ {
		channelS[i] = make(chan struct{})
	}

	var wg sync.WaitGroup
	wg.Add(n)
	global := 0
	var mu sync.Mutex // 创建互斥锁

	for i := 0; i < n; i++ {
		go func(i int) {
			defer wg.Done()
			if i == 0 {
				channelS[0] <- struct{}{} // 启动第一个通道
			}
			<-channelS[i]
			mu.Lock() // 加锁以安全地读取和写入 global
			fmt.Println(i) // 打印当前索引而不是 global
			global++
			if global < n { // 确保不会越界
				channelS[global] <- struct{}{}
			}
			mu.Unlock() // 解锁
		}(i)
	}

	wg.Wait()
}

更正后的关键点

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


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

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?