package main import ( "fmt" "net/http" "os/exec" "runtime" "sync" "time" ) // 验证Hand Off触发场景,覆盖所有核心触发类型 func main() { // 限制P数量为1,放大Hand Off效果(若不触发,G2需等待G1完成) runtime.GOMAXPROCS(1) fmt.Printf("当前P的数量: %d\n", runtime.GOMAXPROCS(0)) // 强制GC和调度器初始化 runtime.GC() time.Sleep(10 * time.Millisecond) // 1. 阻塞式网络I/O触发Hand Off testBlockNetIO() fmt.Println("=== 分割线 ===") // 2. time.Sleep()触发Hand Off testTimeSleep() fmt.Println("=== 分割线 ===") // 3. os/exec执行外部命令触发Hand Off testExecCommand() } // 场景1:阻塞式网络I/O(HTTP请求) func testBlockNetIO() { var wg sync.WaitGroup // 控制执行顺序,避免调度随机性 g1Start := make(chan struct{}) g2Exec := make(chan struct{}) // G1:执行阻塞式HTTP请求 wg.Add(1) go func() { defer wg.Done() close(g1Start) fmt.Println("G1: 开始执行阻塞式HTTP请求") // 阻塞式网络I/O _, err := http.Get("https://www.baidu.com") if err != nil { fmt.Printf("G1: HTTP请求异常: %v\n", err) } fmt.Println("G1: HTTP请求完成") close(g2Exec) }() // 等待G1启动后,启动G2 <-g1Start time.Sleep(50 * time.Millisecond) // G2:验证Hand Off生效(若触发则立即执行) wg.Add(1) go func() { defer wg.Done() fmt.Println("G2: 开始执行(验证网络I/O触发Hand Off)") <-g2Exec fmt.Println("G2: 执行完成") }() wg.Wait() } // 场景2:time.Sleep()触发Hand Off func testTimeSleep() { var wg sync.WaitGroup g1Sleep := make(chan struct{}) // G1:执行time.Sleep() wg.Add(1) go func() { defer wg.Done() close(g1Sleep) fmt.Println("G1: 开始执行time.Sleep(1秒)") time.Sleep(1 * time.Second) fmt.Println("G1: sleep完成,恢复执行") }() // 等待G1进入sleep后,启动G2 <-g1Sleep time.Sleep(50 * time.Millisecond) // G2:验证Hand Off生效 wg.Add(1) go func() { defer wg.Done() fmt.Println("G2: 开始执行(验证time.Sleep触发Hand Off)") }() wg.Wait() } // 场景3:os/exec执行外部命令 func testExecCommand() { var wg sync.WaitGroup g1Exec := make(chan struct{}) g2Started := make(chan struct{}) // G1:执行外部sleep命令 wg.Add(1) go func() { defer wg.Done() close(g1Exec) // 通知G1已启动 fmt.Println("G1: 执行外部命令 sleep 1s") // 关键:在阻塞前让出处理器,确保调度器有机会切换 runtime.Gosched() // 跨平台命令执行 var cmd *exec.Cmd if runtime.GOOS == "windows" { fmt.Println("检测到Windows系统,使用timeout命令") cmd = exec.Command("powershell", "-command", "Start-Sleep -Seconds 1") } else { cmd = exec.Command("sleep", "1") } err := cmd.Run() if err != nil { fmt.Printf("G1: 命令执行错误: %v\n", err) } fmt.Println("G1: 外部命令执行完成") }() // 等待G1启动 <-g1Exec time.Sleep(10 * time.Millisecond) // 短暂等待确保G1进入阻塞 // G2:验证Hand Off生效 wg.Add(1) go func() { defer wg.Done() close(g2Started) fmt.Println("G2: 开始执行(验证os/exec触发Hand Off)") }() // 等待G2启动确认 select { case <-g2Started: fmt.Println("验证成功: G2在G1阻塞期间执行") case <-time.After(500 * time.Millisecond): fmt.Println("警告: G2未及时执行,可能未触发Hand Off") } wg.Wait() }