首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user