- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
为了解决我对 goroutines 的一些误解,我去了 Go playground 并运行了 this code :
package main
import (
"fmt"
)
func other(done chan bool) {
done <- true
go func() {
for {
fmt.Println("Here")
}
}()
}
func main() {
fmt.Println("Hello, playground")
done := make(chan bool)
go other(done)
<-done
fmt.Println("Finished.")
}
如我所料,Go playground 返回错误:Process too long。
这似乎暗示在 other
中创建的 goroutine 会永远运行。
但是当我在自己的机器上运行相同的代码时,我几乎立即得到了这个输出:
Hello, playground.
Finished.
这似乎暗示 other
中的 goroutine 在主 goroutine 完成时退出。 这是真的吗?还是主 goroutine 完成,而另一个 goroutine 继续在后台运行?
最佳答案
编辑:Go Playground 上的默认 GOMAXPROCS 已更改,现在默认为 8。在“过去”的日子里,它默认为 1
。要获得问题中描述的行为,请使用 runtime.GOMAXPROCS(1)
将其显式设置为 1。
移动 Playground ,GOMAXPROCS是 1
( proof )。
这意味着一次执行一个 goroutine,如果该 goroutine 没有阻塞,则调度程序不会被迫切换到其他 goroutine。
您的代码(就像每个 Go 应用程序一样)以执行 main()
函数(主 goroutine)的 goroutine 开始。它启动另一个执行 other()
函数的 goroutine,然后它从 done
channel 接收数据——这会阻塞。所以调度器必须切换到另一个 goroutine(执行 other()
函数)。
在您的 other()
函数中,当您在 done
channel 上发送一个值时,这使得当前 (other()
)和可运行的 main
goroutine。调度器选择继续运行other()
,由于GOMAXPROCS=1
,main()
没有继续运行。现在 other()
启动另一个执行无限循环的 goroutine。调度器选择执行这个 goroutine,它需要永远进入阻塞状态,所以 main()
不会继续。
然后 Go Playground 的沙箱超时作为一种赦免:
process took too long
请注意 Go Memory Model只保证某些事件发生在其他事件之前,你不能保证 2 个并发 goroutines 是如何执行的。这使得输出不确定。
您不得质疑任何不违反 Go 内存模型的执行顺序。如果您希望执行到代码中的某些点(执行某些语句),则需要显式同步(您需要同步您的 goroutines)。
另请注意,Go Playground 上的输出已缓存,因此如果您再次运行该应用程序,它不会再次运行,而是会立即显示缓存的输出。如果您更改代码中的任何内容(例如插入空格或注释)然后再次运行它,它将被编译并再次运行。您会通过增加的响应时间注意到它。不过,使用当前版本 ( Go 1.6),您每次都会看到相同的输出。
当你在本地运行它时,GOMAXPROCS
很可能会大于 1
,因为它默认为可用的 CPU 内核数(自 Go 1.5 起)。所以如果你有一个 goroutine 执行无限循环并不重要,另一个 goroutine 将同时执行,这将是 main()
,当 main()
返回,你的程序终止;它不会等待其他非 main
goroutines 完成(参见 Spec: Program execution )。
另请注意,即使您将 GOMAXPROCS
设置为 1
,您的应用程序很可能会在“短”时间内退出,因为调度程序实现将切换到其他 goroutines 并且而不是永远执行无限循环(但是,如上所述,这是不确定的)。当它执行时,它将是 main()
goroutine,因此当 main()
完成并返回时,您的应用程序将终止。
如前所述,默认情况下 GOMAXPROCS
在 Go Playground 上是 1
。但是允许将其设置为更高的值,例如:
runtime.GOMAXPROCS(2)
如果没有显式同步,执行仍然是不确定的,但是您会观察到不同的执行顺序和终止而不会遇到超时:
Hello, playground
Here
Here
Here
...
<Here is printed 996 times, then:>
Finished.
在 Go Playground 上尝试这个变体.
关于go - Go Playground 和我机器上的 Go 之间存在差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36705801/
我被难住了。如果我对文件路径进行硬编码,则此脚本在我的 Windows 机器上的 Eclipse 中运行良好。如果我尝试接受参数并在我的边缘节点(一个 linux 机器)上运行它,它不会抛出任何特定的
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关闭 8 年前。 这个问题似乎不是关于 a specific programming problem,
我们最近将我们的基础架构从 Solaris(Oracle/Sun Java) 迁移到 AIX(IBM Java)。 我们的客户将使用我们共享的算法(AES)和 key 上传加密文件,一旦加密文件放置在
我想编写一个程序(java),它接受一个文件作为输入,对其进行加密(使用aes128)并通过ftp发送该加密文件,接收者接收它并使用 key 进行解密。我是初学者,有什么帮助可以做到这一点吗?非常感谢
我正在尝试将一些为 1c2 机器 (thumb) 编译的 DLL 导入 WinMobile 6.1 C# 智能设备项目。 然而,当我尝试将它们导入我的 C# 项目时,我得到“无法添加对...的引用”,
我正在寻找 FPGA + 机器。 它应该是入门级定价(例如不超过 200 美元)。 编辑:我想制作一个 ASM 图表并将 FPGA 编程为我在图表中指定的行为 最佳答案 你看过Arduino ? 关于
这是我想完成的: Write a program that stimulates a bean machine Your program should prompt the user to enter
我尝试使用以下命令在 Windows 10 上使用 hyperv 创建一台机器: docker-machine create --driver hyperv default 但它给了我: This m
我有个问题 我的问题是我有一个将 mapred.map.tasks 配置为10的作业(抓取工具),这意味着我的工作将一次创建10个映射器。但是我的集群将 mapred.tasktracker.map.
我正在尝试使用命令重新启动 Docker sudo docker restart a7f8ce75f51f 但我收到以下错误 Error response from daemon: Cannot re
在新机器上引导 Eclipse 是一个非常耗时的过程,您最终会问自己是否真的需要每个插件。但这些都很方便,并且有助于养成一致的习惯。 Eclipse 引导问题包括: 解释/记录需要发生的事情 粘贴正确
我们希望建立一个 Docker 开发节点,我们团队中的任何人都可以将东西部署到其中。 我使用 SSH 创建了一个新的 Docker 机器,如下所示: docker-machine create \
如果可能的话,我想使用 java.util.logging 来做到这一点,有什么想法吗?谢谢。 最佳答案 您可以尝试一下SLF4J . Simple Logging Facade for Java (
当 vagrant up 时,我们的 vagrant box 需要大约 1 小时才能提供第一次运行,在配置过程的最后,我想将盒子打包到本地文件夹中的图像,以便下次需要重建时将其用作基础盒子。我正在使用
我正在为我的图像处理项目构建一个 SVM 线性机,在其中提取正样本和负样本的特征并将其保存到目录中。然后,我使用这些功能训练 SVM,但收到一个无法调试的错误。下面是我用于训练分类器的 train-c
问题描述: 我要将MySQL server 5.7.11 (win32) 安装到Windows server 2012 中。服务器中安装了多个网络接口(interface)卡,我将安装多个绑定(bin
我想安排一台 (AWS) Linux 计算机启动、运行程序,然后自行关闭(以将成本保持在最低水平)。我可以放 mycommand; shutdown 在/etc/rc.local 文件中。但如果我需要
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
如何将此文件的输出发送到另一台 Linux 计算机的主目录。 显然,我想发送此文件的输出: sed '/^\s*#/d;/^$/d' /etc/httpd/conf/httpd.conf 到 nati
我有一个 Linux 机器,我可以使用 SSH 进行 root 访问。 我想使用GDB来调试系统。 这是一个精简的 Debian 软件包;因此,我里面没有任何编译工具。 uname -a 给出: 2.
我是一名优秀的程序员,十分优秀!