目录
1.Goroutine底层原理
定义
Goroutine是Go语言的协程(轻量级线程),是GO支持高并发的基础,属于用户态线程,由Go runtime管理而不是操作系统。
2.Goroutine与线程的区别
3.Goroutine泄露的场景
4.Go如何查看正在执行的goroutine数量
runtime.NumGoroutine()
在Go语言中,要查看当前正在执行的goroutine数量,可以使用runtime
包中的NumGoroutine
函数。这个函数返回当前程序中活跃的goroutine的数量。
下面是一个简单的示例代码,展示如何使用runtime.NumGoroutine()
来打印当前goroutine的数量:
package main
import (
"fmt"
"runtime"
)
func main() {
// 打印当前goroutine的数量
fmt.Println("Number of active goroutines:", runtime.NumGoroutine())
// 创建一个新的goroutine
for i := 0; i < 5; i++ {
go func() {
// 在新的goroutine中执行的操作
fmt.Println("Hello from goroutine")
}()
}
// 再次打印goroutine的数量
fmt.Println("Number of active goroutines after creating a new one:", runtime.NumGoroutine())
}
pprof
包
如果你想要更详细的goroutine信息,比如它们的堆栈跟踪,你可以使用pprof
包来获取这些信息。这里是如何使用pprof
来获取goroutine信息的一个简单例子:
package main
import (
"net/http"
"runtime/pprof"
)
func main() {
http.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
pprof.Lookup("goroutine").WriteTo(w, 1)
})
go http.ListenAndServe(":6060", nil)
// 主goroutine中可以做一些其他事情,或者等待
select {}
}
5.如何控制goroutine并发数量
从Go 1.16开始,官方提供了一个更强大的信号量实现。这个包提供了更高级的信号量功能,可以更好地控制并发。
使用semaphore
package main
import (
"context"
"fmt"
"golang.org/x/sync/semaphore"
"sync"
"time"
)
func worker(id int, s *semaphore.Weighted, wg *sync.WaitGroup) {
defer wg.Done()
// 释放许可证
defer s.Release(1)
fmt.Printf("Worker %d started\n", id)
time.Sleep(time.Second) // 模拟工作
fmt.Printf("Worker %d finished\n", id)
}
func main() {
var wg sync.WaitGroup
s := semaphore.NewWeighted(3) // 最多允许3个goroutine并发执行
for i := 1; i <= 10; i++ {
wg.Add(1)
// 请求一个许可证
if err := s.Acquire(context.Background(), 1); err != nil {
fmt.Println("Failed to acquire semaphore:", err)
return
}
go worker(i, s, &wg)
}
wg.Wait()
}
使用channel
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
fmt.Println("Number of active goroutines:", runtime.NumGoroutine())
ch := make(chan int, 3)
for i := 1; i <= 3; i++ {
ch <- i
}
wg := sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
select {
case ii := <-ch:
go func(ii int) {
defer wg.Done()
fmt.Printf("gid is %d + bus is %d \n", ii, i)
ch <- ii
}(ii)
}
}
fmt.Println("Number of active goroutines:", runtime.NumGoroutine())
wg.Wait()
}