Go:M什么时候会被回收?

2018-10-23  本文已影响0人  沙漠中的猴

测试一

新建一个main.go文件。将下面的代码写入。

package main

import (
    "runtime"
    "sync/atomic"
    "time"
)

var count int64

func test() {
    atomic.AddInt64(&count, 1)
    defer atomic.AddInt64(&count, -1)

    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

    time.Sleep(time.Second)
}

func main() {
    for i := 0; i < 2000; i++ {
        go test()
    }

    for {
        time.Sleep(time.Second)
    }
}

使用GODEBUG命令来执行程序

go build -o main main.go && GODEBUG=schedtrace=1000 ./main

会得到如下内容:

00d3fada0b3:~/go/src# go build -o main main.go && GODEBUG=schedtrace=1000 ./main
SCHED 0ms: gomaxprocs=2 idleprocs=0 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [128 9]
SCHED 1009ms: gomaxprocs=2 idleprocs=1 threads=2008 spinningthreads=0 idlethreads=257 runqueue=0 [0 0]
SCHED 2014ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 3015ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 4027ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 5038ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 6039ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 7042ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]
SCHED 8045ms: gomaxprocs=2 idleprocs=2 threads=2008 spinningthreads=0 idlethreads=2005 runqueue=0 [0 0]

可以看到当前的P(调度器)有两个,都处于idle状态。M总共有2008个,其中2005个处于idle状态。 这就说明空闲状态的M,并没有被回收。

测试二:

将上面的代码中defer runtime.UnlockOSThread()注释掉,造成M死锁状态。然后重新执行代码。

go build -o main main.go && GODEBUG=schedtrace=1000 ./main

会得到如下内容:

00d3fada0b3:~/go/src# go build -o main main.go && GODEBUG=schedtrace=1000 .
SCHED 0ms: gomaxprocs=2 idleprocs=0 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [0 0]
SCHED 1005ms: gomaxprocs=2 idleprocs=0 threads=1982 spinningthreads=0 idlethreads=2 runqueue=0 [19 9]
SCHED 2010ms: gomaxprocs=2 idleprocs=2 threads=11 spinningthreads=0 idlethreads=8 runqueue=0 [0 0]
SCHED 3020ms: gomaxprocs=2 idleprocs=2 threads=11 spinningthreads=0 idlethreads=8 runqueue=0 [0 0]
SCHED 4030ms: gomaxprocs=2 idleprocs=2 threads=11 spinningthreads=0 idlethreads=8 runqueue=0 [0 0]
SCHED 5030ms: gomaxprocs=2 idleprocs=2 threads=11 spinningthreads=0 idlethreads=8 runqueue=0 [0 0]
SCHED 6031ms: gomaxprocs=2 idleprocs=2 threads=11 spinningthreads=0 idlethreads=8 runqueue=0 [0 0]

可以看到存在的M要比之前少了很多。大部分的M都被回收了。

总结

M出问题的时候才会被回收,否则一直存在。

在我们写代码的时候,应注意一下不要重复创建太多的M,造成资源的浪费。

上一篇下一篇

猜你喜欢

热点阅读