在goroutine中使用SMTP的奇怪行为

时间:2016-06-05 01:44:32

标签: go concurrency

我对在goroutine中使用SMTP发现的一些奇怪行为感到困惑。

尝试使用以下代码发送电子邮件时,我的SendMail函数启动(我可以看到日志消息),但永远不会完成。它只是挂起。

Intent dialogIntent = new Intent(applicationCotext, DialogActivity.class);
    dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    applicationCotext.startActivity(dialogIntent);

但是,当我向SendMail添加另一个电话时 - 两个电子邮件都已成功发送。

func main() {
    go SendEmail("TEST")
    for {}
  }

有人可以解释发生了什么吗?

注意,这是一个非常简化的计划任务版本,因此是while循环

发送电子邮件的代码:

func main() {
    go SendEmail("TEST")
    SendEmail("TEST")
    for {}
  }

谢谢!

1 个答案:

答案 0 :(得分:1)

您应该将for{}替换为select{}。永远不要创建一个空的for{}

for{}创建一个永远旋转的循环,但由于循环中没有函数调用(或更准确地堆栈检查和/或分配),调度程序将永远无法对主goroutine进行计划,这反过来又会阻止你的其他goroutine被安排。 (这也可能会占用整个CPU,因为你忙于循环操作系统线程)

最后请参阅我关于GOMAXPROCS的说明。

SendEmail("TEST")运行时获得机会(或更确切地说,多次机会)之后立即调用go SendEmail("TEST"),以便在进入for{}循环之前安排其他goroutine运行。< / p>

使用空的select(select{})代替,主goroutine将无限期地等待而不消耗任何CPU,而是直接产生调度程序。

关于GOMAXPROCS

如果您的GOMAXPROCS为1(在Go 1.5之前默认),您将只有一个OS线程(至少用于运行goroutines),如果您有忙循环,这将阻止任何其他goroutine运行。如果你有GOMAXPROCS&gt; 1运行时仍然可以安排其他goroutine,因为有多个线程用于运行goroutine,但你不应该依赖它。相反,您应该删除任何繁忙的循环。