package main import ( "fmt" "runtime" "sync" "time" ) var wgsp sync.WaitGroup var resultChan = make(chan string, 40) // 刚好容纳 40 个任务结果 // 辅助函数:生成重复字符串(修复语法错误) func repeatStr(str string, count int) string { res := "" for i := 0; i < count; i++ { res += str } return res } // LRQ 任务:直接创建,优先进入本地队列(LRQ) func lrqTask(id int) { defer wgsp.Done() time.Sleep(20 * time.Millisecond) // 模拟任务耗时 resultChan <- fmt.Sprintf("lrq_%d", id) // 直接标记为 LRQ 任务 } // GRQ 任务:通过 GC 强制进入全局队列(GRQ) func grqTask(id int) { defer wgsp.Done() // 关键:通过 runtime.GC() 触发调度,让 Goroutine 进入 GRQ runtime.GC() time.Sleep(20 * time.Millisecond) // 模拟任务耗时 resultChan <- fmt.Sprintf("grq_%d", id) // 直接标记为 GRQ 任务 } func main() { // 固定 P=2,确保窃取场景 runtime.GOMAXPROCS(2) fmt.Println("=== 工作窃取优先级验证:LRQ 任务 > GRQ 任务 ===") fmt.Printf("P 数量:%d\n", runtime.GOMAXPROCS(-1)) fmt.Println("实验逻辑:") fmt.Println("1. 创建 20 个 LRQ 任务(进入 P0/P1 的本地队列);") fmt.Println("2. 创建 20 个 GRQ 任务(通过 GC 强制进入全局队列);") fmt.Println("3. 空闲 P 会优先窃取其他 P 的 LRQ 任务,再执行 GRQ 任务;") fmt.Println("4. 验证:前 20 个完成的任务中,LRQ 任务占比 > 15 个\n") // 步骤1:创建 20 个 LRQ 任务(优先进入 LRQ) fmt.Println("创建 20 个 LRQ 任务...") for i := 0; i < 20; i++ { wgsp.Add(1) go lrqTask(i) } time.Sleep(100 * time.Millisecond) // 让 LRQ 任务先进入队列 // 步骤2:创建 20 个 GRQ 任务(强制进入 GRQ) fmt.Println("创建 20 个 GRQ 任务...") for i := 0; i < 20; i++ { wgsp.Add(1) go grqTask(i) } // 步骤3:等待所有任务完成,关闭通道(无阻塞) go func() { wgsp.Wait() close(resultChan) }() // 步骤4:统计前 20 个完成的任务(零误差) lrqCnt := 0 grqCnt := 0 fmt.Println("\n开始执行任务,统计前 20 个完成的任务...") for i := 0; i < 20; i++ { res, ok := <-resultChan if !ok { fmt.Printf("⚠️ 通道提前关闭,仅统计到 %d 个任务\n", i) break } fmt.Printf("第%d个完成:%s\n", i+1, res) // 直接判断前缀,无误差 if res[:3] == "lrq" { lrqCnt++ } else if res[:3] == "grq" { grqCnt++ } } // 输出结果与结论 sep := repeatStr("=", 50) fmt.Printf("\n%s", sep) fmt.Printf("\n前 20 个完成的任务统计:\n") fmt.Printf("LRQ 任务(含窃取的):%d 个\n", lrqCnt) fmt.Printf("GRQ 任务:%d 个\n", grqCnt) fmt.Printf("有效统计任务数:%d 个\n", lrqCnt+grqCnt) fmt.Printf("%s", sep) // 验证逻辑:LRQ 任务占比 > 15 个即成功 if lrqCnt > 15 { fmt.Println("\n\n✅ 验证成功!") fmt.Printf("结论:LRQ 任务占比 %d/20,远高于 GRQ 任务,证明空闲 P 优先窃取其他 P 的 LRQ 任务,工作窃取优先级策略生效。\n", lrqCnt) } else if lrqCnt+grqCnt == 0 { fmt.Println("\n\n❌ 验证失败") fmt.Println("原因:任务未执行,可重启程序或延长任务耗时。") } else { fmt.Println("\n\n❌ 验证失败(极罕见)") fmt.Println("结论:LRQ 任务占比不足,可重启程序重试。") } }