zoukankan      html  css  js  c++  java
  • 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.这个问题是我解决的,哈哈哈。

  • 相关阅读:
    使用RedisTemplate的操作类访问Redis(转载)
    Redis集群方案(来自网络)
    Scale-up and Scale-out(转载)
    数据结构和算法分析 优先队列
    数据结构和算法分析 排序
    linux下的常用命令
    Java HashMap的工作原理(转载)
    二叉查找树(转载)
    Redis实现之对象(三)
    Redis实现之对象(二)
  • 原文地址:https://www.cnblogs.com/yudidi/p/12443735.html
Copyright © 2011-2022 走看看