首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 验证Hand Off非触发场景,覆盖所有核心非触发类型
|
||||
func main() {
|
||||
// 限制P数量为1,关闭异步抢占后,G2必须等待G1完成
|
||||
runtime.GOMAXPROCS(1)
|
||||
fmt.Printf("当前P的数量: %d\n", runtime.GOMAXPROCS(0))
|
||||
|
||||
// 1. 纯CPU密集型计算(非触发)
|
||||
testCPUCompute()
|
||||
fmt.Println("=== 分割线 ===")
|
||||
|
||||
// 2. 带缓冲Channel(非满)(非触发)
|
||||
testBufferedChan()
|
||||
fmt.Println("=== 分割线 ===")
|
||||
|
||||
// 3. 非阻塞网络操作(非触发)
|
||||
testNonblockNet()
|
||||
}
|
||||
|
||||
// 场景1:纯CPU密集型计算(核心强化:避免调度器抢占干扰)
|
||||
func testCPUCompute() {
|
||||
var wg sync.WaitGroup
|
||||
// 用于确认G1完全执行完毕后,G2才打印
|
||||
g1Done := make(chan struct{})
|
||||
|
||||
// G1:1亿次累加(纯CPU计算,无阻塞)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
fmt.Println("G1: 开始纯CPU计算(10亿次累加)")
|
||||
start := time.Now()
|
||||
var sum int64 = 0
|
||||
// 密集计算,确保长时间占据P
|
||||
for i := 0; i < 100000000; i++ {
|
||||
sum += int64(i)
|
||||
// 禁止调度器抢占(仅用于验证,生产环境不建议)
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
}
|
||||
fmt.Printf("G1: 计算完成,耗时%v,sum=%d\n", time.Since(start), sum)
|
||||
close(g1Done)
|
||||
}()
|
||||
|
||||
// G2:必须等待G1完成后才能执行(验证无Hand Off)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// 阻塞直到G1完成
|
||||
<-g1Done
|
||||
fmt.Println("G2: 尝试执行(无Hand Off则等待G1完成)")
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// 场景2:带缓冲Channel(非满)(非触发)
|
||||
func testBufferedChan() {
|
||||
var wg sync.WaitGroup
|
||||
ch := make(chan int, 2)
|
||||
g1Done := make(chan struct{})
|
||||
|
||||
// G1:向未满的Channel发送数据(无阻塞)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
fmt.Println("G1: 向带缓冲Channel发送数据(非满)")
|
||||
ch <- 1
|
||||
ch <- 2
|
||||
// 模拟耗时操作,确保占据P
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
fmt.Println("G1: 数据发送完成")
|
||||
close(g1Done)
|
||||
}()
|
||||
|
||||
// G2:必须等待G1完成后才能执行
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-g1Done
|
||||
fmt.Println("G2: 尝试执行(无Hand Off则等待G1)")
|
||||
val := <-ch
|
||||
fmt.Printf("G2: 接收数据%d\n", val)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
}
|
||||
|
||||
// 场景3:非阻塞网络操作(非触发)- 修正SetNonblock调用方式
|
||||
func testNonblockNet() {
|
||||
var wg sync.WaitGroup
|
||||
g1Done := make(chan struct{})
|
||||
|
||||
// 先拨号建立连接
|
||||
conn, err := net.Dial("tcp", "www.baidu.com:80")
|
||||
if err != nil {
|
||||
fmt.Printf("创建连接异常: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// 转换为TCPConn并获取底层文件描述符,设置非阻塞模式
|
||||
tcpConn, ok := conn.(*net.TCPConn)
|
||||
if !ok {
|
||||
fmt.Println("转换为TCPConn失败")
|
||||
return
|
||||
}
|
||||
file, err := tcpConn.File()
|
||||
if err != nil {
|
||||
fmt.Printf("获取文件描述符失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 设置非阻塞模式
|
||||
if err := syscall.SetNonblock(syscall.Handle(int(file.Fd())), true); err != nil {
|
||||
fmt.Printf("设置非阻塞失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// G1:非阻塞写数据(无OS级阻塞)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
fmt.Println("G1: 非阻塞写入网络数据")
|
||||
_, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n"))
|
||||
if err != nil {
|
||||
if opErr, ok := err.(*net.OpError); ok && opErr.Temporary() {
|
||||
fmt.Println("G1: 非阻塞写入暂时不可用(正常非阻塞行为)")
|
||||
} else {
|
||||
fmt.Printf("G1: 非阻塞写入异常: %v\n", err)
|
||||
}
|
||||
}
|
||||
// 模拟耗时操作,占据P
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
fmt.Println("G1: 非阻塞写入完成")
|
||||
close(g1Done)
|
||||
}()
|
||||
|
||||
// G2:必须等待G1完成后才能执行
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-g1Done
|
||||
fmt.Println("G2: 尝试执行(无Hand Off则等待G1完成)")
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user