Golang Goroutine随机无报错停止问题求助
问题分析与修复方案
核心问题点
- 泵状态未重置:处理完车辆加油后,未将
pump.IsOccupied设为false,导致泵永久处于「占用」状态,后续循环的if pump.IsOccupied == false条件永远不满足,goroutine不再进入处理逻辑,表现为停止响应。 - 锁逻辑错误:
- 在
select的case分支中,持有Mutex的情况下执行time.Sleep,无意义地阻塞其他可能访问该泵的操作。 - 解锁逻辑不一致:仅
default分支有提前解锁,case分支需到if块结束才解锁,易引发锁占用问题。
- 在
- 竞态条件:对
pump.IsOccupied的读写未通过Mutex同步,可能导致goroutine读取到旧状态,引发逻辑异常。 - 流程未闭环:加油完成后,未将车辆传递到后续的
registerQueues,也未清理pump.CurrentCar,导致泵状态无法恢复。
修复后的代码
func pumpOperation(pump *Pump, pumpQueue *EntryQueue, registerQueues *[]*RegisterQueue, outputs *[]Car, maxCarCount int64, wg *sync.WaitGroup) { defer wg.Done() // 初始化随机数种子,避免多个goroutine生成重复随机值 rand.Seed(time.Now().UnixNano() + int64(rand.Intn(1000))) for { // 加锁检查泵的可用状态,避免竞态 pump.Mutex.Lock() isFree := !pump.IsOccupied && strings.Compare(pump.Type, pumpQueue.Type) == 0 pump.Mutex.Unlock() if !isFree { time.Sleep(1 * time.Millisecond) continue } pump.Mutex.Lock() // 双重检查:防止解锁到重新加锁的间隙被其他goroutine占用 if pump.IsOccupied || strings.Compare(pump.Type, pumpQueue.Type) != 0 { pump.Mutex.Unlock() continue } select { case car := <-pumpQueue.Queue: // 设置泵为占用状态后立即解锁,sleep无需持有锁 pump.CurrentCar = car pump.CurrentCar.PumpEntry = time.Now() pump.IsOccupied = true pump.Mutex.Unlock() // 模拟加油服务时间 serviceTime := rand.Intn(pump.ServiceMax-pump.ServiceMin+1) + pump.ServiceMin time.Sleep(time.Duration(serviceTime) * time.Millisecond) // 加油完成,重置泵状态并流转车辆 pump.Mutex.Lock() pump.IsOccupied = false pump.CurrentCar = nil // 将车辆送入对应类型的登记队列(可根据实际逻辑调整) for _, rq := range *registerQueues { if strings.Compare(rq.Type, car.Type) == 0 { rq.Queue <- car break } } pump.Mutex.Unlock() default: // 无车辆等待,解锁后短暂休眠降低CPU占用 fmt.Printf("No car in queue, %s pump waits\n", pump.Type) pump.Mutex.Unlock() time.Sleep(1 * time.Millisecond) } } }
关键修改说明
- 重置泵状态:加油完成后强制将
pump.IsOccupied设为false,清空pump.CurrentCar,确保泵能重新接收新车辆。 - 优化锁持有时间:仅在修改/读取泵状态的临界区持有Mutex,
time.Sleep前释放锁,避免不必要的阻塞。 - 双重检查状态:重新加锁后再次确认泵的状态,防止间隙时间被其他goroutine抢占,消除竞态风险。
- 同步状态读写:所有对
pump.IsOccupied的操作都通过Mutex保护,保证状态一致性。 - 闭环流程:添加车辆到登记队列的逻辑,确保业务流程完整(可根据实际需求调整该部分逻辑)。
内容的提问来源于stack exchange,提问作者urula
相关产品推荐
相关产品推荐

