我知道go例程可以执行一些阻塞操作,想知道goroutine是否可以像常规函数一样调用用户定义的阻塞函数。用户定义的阻止功能具有几个步骤,如step1,step2。
换句话说,我想找出我们是否可以在go例程中嵌套嵌套的阻塞调用。
UPDATE:
最初的目的是找到goroutine使用的堆栈大小,特别是对于嵌套的阻塞调用。对困惑感到抱歉。多亏了答案和评论,我创建了以下具有100,000个goroutine的函数,在我的Ubuntu桌面上占用了782MB的虚拟内存和416MB的常驻内存。每个go例程堆栈平均需要78KB的内存。这是正确的说法吗?
package main
import (
"fmt"
"time"
)
func f(a int) {
x := f1(a);
f2(x);
}
func f1(a int) int {
r := step("1a", a);
r = step("1b", r);
return 1000 * a;
}
func f2(a int) {
r := step("2a", a);
r = step("2b", r);
}
func step(a string, b int) int{
fmt.Printf("%s %d\n", a, b);
time.Sleep(1000 * time.Second)
return 10 * b;
}
func main() {
for i := 0; i < 100000; i++ {
go f(i);
}
//go f(20);
time.Sleep(1000 * time.Second)
}
我相信您是对的,尽管我不确定“虚拟”和“常驻”内存之间的关系,但可能存在一些重叠。
要考虑的一些事情:您正在运行100,000,而不是10,000。
堆栈本身可能包含用于printfs的字符串,方法参数等。
从go 1.2开始,默认堆栈大小(每个go例程)为8KB,这也许可以解释其中的某些内容。
从1.3版开始,它还使用exponentially increasing堆栈大小,但是我怀疑那是您遇到的问题。
答案是肯定的。
goroutine是一个“轻量级线程”,这意味着它可以独立于程序中的其他代码执行操作。就像启动一个新程序一样,但是您可以使用golang提供的结构(通道,锁等)与其他代码进行通信。
P.S。一旦main函数结束,所有goroutine都会被杀死(这就是为什么您需要time.Sleep()的原因)
这是一个简单的示例(由于其限制,它不会在golang游乐场中运行:
package main
import (
"fmt"
"time"
)
func saySomething(a, b func()){
a()
b()
}
func foo() {
fmt.Println("foo")
}
func bar() {
fmt.Println("bar")
}
func talkForAWhile() {
for {
saySomething(foo, bar)
}
}
func main() {
go talkForAWhile()
time.Sleep(1 * time.Second)
}