登录
首页 >  Golang >  Go问答

请教一个goroutines问题

来源:SegmentFault

时间:2023-02-16 15:27:46 460浏览 收藏

对于一个Golang开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《请教一个goroutines问题》,主要介绍了go,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!

问题内容

下面代码片段,为什么执行到counter3000多,就不执行了。另外如果去掉

fmt.Println("counter in main:", counter)
的注释,就可以执行完毕。这是为什么啊?

09-02 update:是在

main()
中第二个
for
循环卡死了,就是感觉
goroutines
没有执行完或者没有按预期执行(预期最后
counter
值会为
9000
)。但是去掉注释就不会卡死。另外今天在公司电脑,这个偶尔会卡死,偶尔又不会卡死,不知道为什么。

package main

import (
    "fmt"
    "sync"
)

var counter int = 0

func Count(i int, lock *sync.Mutex) {
    lock.Lock()
    fmt.Println("Before Count()", i, counter)
    counter++
    fmt.Println("After Count()", i, counter)
    lock.Unlock()
}

func main() {
    lock := &sync.Mutex{}
    for i := 0; i = 9000 {
            break
        }
    }
}

正确答案

恰好研究过这个问题,我来尝试回答一下吧。

这属于golang调度器的问题。截止到目前版本(1.5),golang的调度器是不完全抢占的,也就是说并不是在任何情况下都能够触发抢断。只有当阻塞操作(IO、channel等)、系统调用、非内联函数调用或者显式调用

runtime.Gosched()
时才能够触发调度,而且即使能够触发调度也不一定真的会发生调度,后台的sysmon会查看当前goroutine的运行时间,过长才会进行调度。

如果去掉了

fmt.Println
,第二个循环就处于没有调度机会的状态,这个goroutine会永远占用时间片。

你说的无法稳定复现的问题,因为golang版本不同、机器是否多核、调度顺序不同都会发生影响,所以确实是有一些随机性的。

一些详情可以看这篇文章:http://cholerae.com/2015/05/09/%E5%85%B3%E4%BA%8Egoroutine%E8%B0%83%E5%BA%A6%E6%97%B6%E6%9C%BA%E7%9A%84%E8%AF%95%E9%AA%8C/

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于Golang的相关知识,也可关注golang学习网公众号。

声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表