Go 1.14之前的死循环Case

第一个例子

package main

import (
    "runtime"
    "time"
)

func main() {
    runtime.GOMAXPROCS(1)
    go func() {
        for {
        }
    }()
    time.Sleep(time.Millisecond)
    println("OK")
}

不会打印OK

关于 Go1.14,你一定想知道的性能提升与新特性

为什么不会打印?

> [golang高并发模型](https://www.yangyanxing.com/article/golang-concurrency.html)

第二个例子

package main

import (
	"fmt"
	"runtime"
	"time"
)

func main() {
	for i := 0; i < runtime.NumCPU(); i++ {
		go func() {
			for {
			}
		}()
	}
	for {
		time.Sleep(100)
		fmt.Println(time.Now())
	}
}

也是打印一会儿之后就卡死了。

第三个例子

func main() {
 var count int32 =0
  for i:=0;i<=10;i++  {
  go func() {
   for   {
    atomic.AddInt32(&count,1)
   }
  }()

  go func() {
   for   {
    fmt.Println(count==1)
   }
  }()
 }
 time.Sleep(time.Hour)
}

打印一会儿之后,程序会卡死。
表面上看 atomic.AddInt32(&count,1)有函数调用,那这里为什么还是卡死了呢。

=我是分割线====

因为此"函数调用"非彼"函数调用"。

思考一个问题:
Q: 如何判断某个语句是否会导致函数调用呢?
A: 就是把他们反汇编之后看这些语句是否对应着CALL指令就知道了。

我们分别看一下fmt.Printlnatomic.AddInt32的反汇编代码就知道了。查看反汇编的指令go tool compile -S main.go

所以我们可以看到atomic.AddInt32是不会触发函数调用的,fmt.Println会触发函数调用的,进而可以检查自己的抢占flag,决定是否继续执行,还是让出自己。

感谢go夜读群友的提问和讨论,使得我可以更深入理解抢占式调度的含义。PS.这个问题是我解决的,哈哈哈。

原文地址:https://www.cnblogs.com/yudidi/p/12443735.html