Goroutine是协作调度的.这是否意味着不产生执行结果的goroutine将导致goroutine逐一运行? [英] Goroutines are cooperatively scheduled. Does that mean that goroutines that don't yield execution will cause goroutines to run one by one?

查看:99
本文介绍了Goroutine是协作调度的.这是否意味着不产生执行结果的goroutine将导致goroutine逐一运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自: http://blog.nindalf.com/how-goroutines-work/

由于goroutine是协同调度的,因此不断循环的goroutine会使同一线程上的其他goroutine饿死.

As the goroutines are scheduled cooperatively, a goroutine that loops continuously can starve other goroutines on the same thread.

goroutine很便宜,并且如果被阻塞,不会导致对其进行复用的线程阻塞

Goroutines are cheap and do not cause the thread on which they are multiplexed to block if they are blocked on

  • 网络输入
  • 睡觉
  • 渠道运营或
  • 阻止同步包中的基元.
  • network input
  • sleeping
  • channel operations or
  • blocking on primitives in the sync package.

因此,鉴于以上所述,假设您有类似这样的代码,除了循环随机次数并打印总和外,什么也不做:

So given the above, say that you have some code like this that does nothing but loop a random number of times and print the sum:

func sum(x int) {
  sum := 0
  for i := 0; i < x; i++ {
    sum += i
  }
  fmt.Println(sum)
}

如果您使用goroutines之类的

if you use goroutines like

go sum(100)
go sum(200)
go sum(300)
go sum(400)

如果只有一个线程,goroutine程序会一一运行吗?

will the goroutines run one by one if you only have one thread?

推荐答案

所有kerker评论的汇编和整理.

抢先是指内核(运行时)允许线程运行特定的时间,然后在其他线程不做任何事情或不知道任何事情的情况下让其执行.在OS内核中,通常使用硬件中断来实现.进程不能阻止整个操作系统.在协作式多任务处理中,线程必须显式地让他人执行.如果不是这样,它可能会阻塞整个过程甚至整个机器. Go就是这样做的.它在goroutine可以产生执行的一些非常特定的点.但是,如果goroutine仅针对{}执行,那么它将锁定整个过程.

A compilation and tidying of all of creker's comments.

Preemptive means that kernel (runtime) allows threads to run for a specific amount of time and then yields execution to other threads without them doing or knowing anything. In OS kernels that's usually implemented using hardware interrupts. Process can't block entire OS. In cooperative multitasking thread have to explicitly yield execution to others. If it doesn't it could block whole process or even whole machine. That's how Go does it. It has some very specific points where goroutine can yield execution. But if goroutine just executes for {} then it will lock entire process.

但是,引用中没有提到运行时中的最新更改. fmt.Println(sum)可能导致其他goroutine被调度,因为较新的运行时将在函数调用时调用调度程序.

However, the quote doesn't mention recent changes in the runtime. fmt.Println(sum) could cause other goroutines to be scheduled as newer runtimes will call scheduler on function calls.

如果您没有任何函数调用,只需进行一些数学运算,那么是的,goroutine将锁定线程,直到其退出或遇到可能使他人执行的事情为止.这就是for {}在Go中不起作用的原因.更糟糕的是,由于GO的工作原理,即使GOMAXPROCS> 1,它仍然会导致进程挂起,但是无论如何您都不应依赖于此.很高兴了解这些东西,但不要指望它.甚至有人建议在您这样的循环中插入调度程序调用

If you don't have any function calls, just some math, then yes, goroutine will lock the thread until it exits or hits something that could yield execution to others. That's why for {} doesn't work in Go. Even worse, it will still lead to process hanging even if GOMAXPROCS > 1 because of how GC works, but in any case you shouldn't depend on that. It's good to understand that stuff but don't count on it. There is even a proposal to insert scheduler calls in loops like yours

Go的运行时所做的主要事情是尽其所能,使每个人都能执行,而不会饿死任何人.语言规范中未指定该操作的方式,并且将来可能会更改.如果关于循环的提议将被实施,那么即使没有函数调用也可能发生切换.目前,您唯一需要记住的是,在某些情况下,函数调用可能会导致goroutine产生执行结果.

The main thing that Go's runtime does is it gives its best to allow everyone to execute and don't starve anyone. How it does that is not specified in the language specification and might change in the future. If the proposal about loops will be implemented then even without function calls switching could occur. At the moment the only thing you should remember is that in some circumstances function calls could cause goroutine to yield execution.

要解释Akavall答案中的切换,在调用fmt.Printf时,它要做的第一件事是检查是否需要增加堆栈并调用调度程序.它可能会切换到另一个goroutine.是否切换取决于其他goroutine的状态以及调度程序的确切实现.像任何调度程序一样,它可能会检查是否有饥饿的goroutines应该执行.在许多迭代中,函数调用有更大的机会进行切换,因为其他人则挨饿了更长的时间.经过几次迭代,goroutine在饥饿发生之前就完成了.

To explain the switching in Akavall's answer, when fmt.Printf is called, the first thing it does is checks whether it needs to grow the stack and calls the scheduler. It MIGHT switch to another goroutine. Whether it will switch depends on the state of other goroutines and exact implementation of the scheduler. Like any scheduler, it probably checks whether there're starving goroutines that should be executed instead. With many iterations function call has greater chance to make a switch because others are starving longer. With few iterations goroutine finishes before starvation happens.

这篇关于Goroutine是协作调度的.这是否意味着不产生执行结果的goroutine将导致goroutine逐一运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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