goruntine调用匿名函数遇到的坑

1.goruntine调用匿名函数

package main

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


func print(i int){
	fmt.Print(i,"\t")
}
func foo() {
	//runtime.GOMAXPROCS(1)  //单核
	time.Sleep(time.Second)
	for i := 0; i < 50; i++ {
			go func() {
				fmt.Print(i,"\t")
			}()
		//go print(i)
	}
	runtime.Gosched()
	time.Sleep(time.Second)
}
func main(){
	foo()
}
// 运行结果大部分是50,相对应for 循环 goroutine跑的慢
2	14	14	14	14	15	15	16	17	18	18	18	18	19	19	20	21	21	21	21	22	
23	26	26	26	26	42	46	46	46	50	50	50	50	46	50	50	50	50	46	50	38
50	50	50	50	46	50	50	50	
// 单核运行结果全部是50,相对应for 循环 goroutine跑的慢
50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50
50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50	50
50	50	50	50	50	50	50	50	

2.goruntine调用普通函数

package main

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


func print(i int){
	fmt.Print(i,"\t")
}
func foo() {
    //runtime.GOMAXPROCS(1)   //单核
	time.Sleep(time.Second)
	for i := 0; i < 50; i++ {
		   //go func() {
		   //fmt.Print(i,"\t")
		   //}()
		go print(i)
	}
	runtime.Gosched()
	time.Sleep(time.Second)
}
func main(){
	foo()
}
 // 运行结果,这是因为有个参数i需要压栈需要获取i的值
 0	10	4	5	6	7	8	2	13	17	15	18	12	9	1	11	14	22	19	20
 21	16	23	24	25	3	49	38	39	40	41	42	43	44	45	26	47	28	29	27
 46	36	32	37	33	30	34	35	31	48	
 
 // 单核运行结果,这是因为有个参数i需要压栈需要获取i的值
 49	0	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18
 19	20	21	22	23	24	25	26	27	28	29	30	31	32	33	34	35	36	37	38
 39	40	41	42	43	44	45	46	47	48	
 //是49 - 0...8并不是0...49,这是为什么呢?
 //其实,go 在把 goroutine放入队列(gosched内容会有另外的篇幅来说明)的时候还做了
 //一件很特别的事:proc:4799 (next),代码内容如下:
   if next {
    retryNext:
    oldnext := _p_.runnext
    if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
        goto retryNext
    }
    if oldnext == 0 {
        return
    }
    // Kick the old runnext out to the regular run queue.
    gp = oldnext.ptr()
 }
//这段代码的意思是 go 会把每个 P 所管理的最后一个 goroutine 放入 next 位置。为什么??
//这是 go 设计认为或者是有过测试:如果一个 P 的 goroutine 队列在顺序执行的时候,
//因为 go sched 会有很多抢占或者调度。那么从被执行的概率上来分析的话,放入一个
//next 位置可使得每个 goroutine 的执行概率是相当的。
//这个next的位置也就决定了49为什么最先打印。
    go func(i int) {
			fmt.Print(i,"\t")
		}(i)
		等效于go print(i)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值