time.Sleep会阻止goroutine吗? [英] Will time.Sleep block goroutine?

查看:92
本文介绍了time.Sleep会阻止goroutine吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下一个代码:

par.go

package main

import (
    "runtime";
    "time"
)

func main() {
    runtime.GOMAXPROCS(4)
    ch := make(chan int)
    n := 1
    for i := 0; i < n; i++ {
        go func() {
            time.Sleep(60 * time.Second)
            ch <- 1
        }();
    }
    for i := 0; i < n; i++ {
        <-ch
    }
}

我接下来使用它来运行它:

I use next to run it:

$ go build par.go
$ time ./par

然后,确认此过程中有多少个线程:

Then, confirm how many threads in this process:

$ ps -ef | grep par
shubunt+  3670 32131  0 12:35 pts/0    00:00:00 ./par
$ cat /proc/3670/status | grep -i threads
Threads:        5

您可以看到有5个线程.

You can see there are 5 threads.

如果我在代码中更改 n 的值,则情况将是下一个:

If I change the value of n in code, then situations are next:

n := 100, Threads is 8
n := 10000, Threads is 9
n := 100000, Threads is 9
n := 1000000, Threads is 9
n := 2000000, Threads is 10

我知道,去调度程序遵循 MPG 模型,这里 P = 4 ,所以 M = 4 M 1:1 KSE (内核线程).如果任何goroutine处于任何阻塞状态,则 P 将与当前的 M 分离,并找到空闲的 M 或新的 M 找不到.

I know, go scheduler follow MPG model, here P = 4, so M = 4, M is 1:1 with KSE(Kernel threads). If any goroutine in any blocking status, the P will detached from current M, and find a idle M or new a M if can't find.

所以,我的问题是: time.Sleep 是否真的阻塞了goroutine?如果不是,当我将 n 的值从 1 增加到 2000000 时,为什么会有新线程出现?如果是,那么那里有 60秒,为什么只是调度程序又增加了一个新的 M ,我希望那里会有很多新线程?

So, my question is: is time.Sleep really blocking goroutine? If not, why new threads there when I increase value of n from 1 to 2000000? If yes, there is 60 seconds there, why just scheduler new a little new M, I expect a lots of new threads there?

更新:

test.go:

package main

import (
    "io/ioutil"
    "os"
    "runtime"
    "strconv"
)

func main() {
    runtime.GOMAXPROCS(2)
    data := make([]byte, 128*1024*1024)
    for i := 0; i < 200; i++ {
        go func(n int) {
            for {
                err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm)
                if err != nil {
                    println(err)
                    break
                }
            }
        }(i)
    }
    select {}
}

如果不使用 Sleep ,请使用真实的IO,我的计算机上的线程号将为 202 .

If not use Sleep, use real IO, the threads number will be 202 on my machine.

所以,我的问题还与上述两个示例的区别有关,当我应该担心调度程序会为我生成太多内核线程吗?

So, my question also related to the difference of above 2 examples, when I should worry about scheduler generate too many kernel threads for me?

推荐答案

[我]的时间.睡眠真的阻塞了goroutine吗?

[I]s time.Sleep really blocking goroutine?

是的

但是goroutine如何实际调度到线程是一个复杂的过程,b)每个版本的发布都不同,c)架构之间可能会有所不同,并且d)语言未指定.而"MPG模型"是指如果调度程序是如何工作的,那么它就是一个准确的模型.

But how goroutines are actually scheduled to threads is a) complicated, b) different in every release, c) can be different from architecture to architecture and d) is not specified by the language. While the "MPG model" is an accurate model if how the scheduler works it is just a model.

如果调度程序确定10个线程足以运行200'000个goroutine,因为它们都是 time.Sleep ,那么10个线程就足够了.

If the scheduler determines that 10 threads are enough to not run 200'000 goroutines as they all are time.Sleeping then 10 threads are enough.

基本上,无需担心或思考Go中的此类内容(与其他语言(此类语言必须特别注意此类特性)形成鲜明对比).阻止"只是意味着下一条语句不能立即执行,因为实际的语句还没有结束.如果原因不尽相同,可能会发生这种情况.睡眠除了等待,等待表格RAM,等待磁盘或等待网络数据外,什么都不做.以相同的方式处理所有内容将简化调度程序,但会使调度程序变差.所以不,时间.睡眠不会阻塞goroutine.问题是阻止goroutine".不是具有明确含义的东西.而且不需要定义它,因为对此没有什么有趣的了解.

Basically there is nothing to worry or think about such stuff in Go (in stark contrast to other languages where extreme care has to be devoted to such peculiarities). "Blocking" just means that the next statement cannot be executed right away as the actual statement is not finished jet. This may happen for a plethora if reasons ranging from time.Sleep which does nothing except wait, waiting form RAM, waiting for disk or waiting for network data. Handling all in the same manner would simplify the scheduler but make it a bad one. So no, time.Sleep does not block the goroutine. The problem is "block goroutine" is not something with a defined meaning. And it need not be defined as there is nothing interesting to know about it.

更新:

[W]我应该担心调度程序为我生成太多内核线程吗?

[W]hen I should worry about scheduler generate too many kernel threads for me?

从不.

有两种不同的情况:A)编写普通的,合理的生产代码,以及B)编写经过手工设计的代码,这些代码经过精心设计以创建许多线程,这些线程都在磁盘IO中等待完成.当然,您可以故意欺骗调度程序和OS,并提出一个病理程序,该程序会创建过多的线程(可以欺骗调度程序 的问题是问题#4056),但不是值得担心的事情.只是不要故意做愚蠢的事情.

There a two different scenarios: A) writing normal, sensible production code and B) writing handcrafted code which is carefully designed to create lots of threads which are all waiting in disk IO to finish. Of course you can deliberately trick the scheduler and the OS and come up with a pathological program which creates too much threads (this problem that the scheduler can be tricked is addresses in issue #4056) but that is not something to worry about. Just do not deliberately do stupid things.

有很多方法可以欺骗您的计算机.编写简洁代码是一种方法.种族探测器有助于识别它们.在编写竞赛条件之前担心竞赛条件是一件好事(因为这种情况会发生).可能会创建过多的线程,您可以向操作系统询问线程数.并且在万一出现的情况太多的情况下:修复它.但这不太可能.有点像OOM错误:编写OOM的代码非常简单,但是在编写代码时不必担心OOM.如果您体验过OOM,则可以进行重新设计,但是不必担心OOM以及您需要了解OOM,如何防止它以及如何执行它,而不必着手进行任何琐碎的项目.除非您已经知道数据使用了很多内存.此处相同:如果您知道您的代码将执行大量 并发磁盘IO,而这对域是本征,那么您可能会为此担心并用代码来处理,但是每种语言的技术都是相同的.

There are lots of ways to trick your computer. Writing racy code is one way. The race detector helps identifying them. Worrying about race conditions before writing them is a good thing (as this happens). Creating too many threads can happen and you can ask your OS for the thread count. And in the unlikely event that there are too many: Fix it. But this is unlikely. Its a bit like OOM errors: It is dead simple to write code which OOMs but there is nothing to worry constantly about OOM while writing code. If your experience OOM you redesign but you do not start any trivial project by worrying about OOM and what you need to know about OOM, how to prevent it and what to do about it. Unless you know already that your data uses lots of memory. Same here: If you know that your code will do massive concurrent disk-IO and this is intrinsic to the domain then you might worry about this and handle this in code but the techniques are the same in every language.

这篇关于time.Sleep会阻止goroutine吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆