- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试更好地了解 Go 程序中如何安排 goroutines,尤其是在哪些点上它们可以屈服于其他 goroutines。我们知道 goroutine 在 syscals 上产生会阻塞它,但显然这不是全部。
This question引起了一些类似的担忧,评分最高的答案说 goroutine 也可以打开函数调用,因为这样做会调用调度程序来检查堆栈是否需要增长,但它明确表示
If you don't have any function calls, just some math, then yes,goroutine will lock the thread until it exits or hits something thatcould yield execution to others.
我写了一个简单的程序来验证和证明:
package main
import "fmt"
var output [30]string // 3 times, 10 iterations each.
var oi = 0
func main() {
runtime.GOMAXPROCS(1) // Or set it through env var GOMAXPROCS.
chanFinished1 := make(chan bool)
chanFinished2 := make(chan bool)
go loop("Goroutine 1", chanFinished1)
go loop("Goroutine 2", chanFinished2)
loop("Main", nil)
<- chanFinished1
<- chanFinished2
for _, l := range output {
fmt.Println(l)
}
}
func loop(name string, finished chan bool) {
for i := 0; i < 1000000000; i++ {
if i % 100000000 == 0 {
output[oi] = name
oi++
}
}
if finished != nil {
finished <- true
}
}
注意:我知道在数组中放入一个值并在不同步的情况下递增 oi
不太正确,但我想让代码简单并且没有可能导致的事情交换。毕竟,可能发生的最糟糕的事情是在不推进索引(覆盖)的情况下输入一个值,这没什么大不了的。
不同于this answer ,我避免使用作为 goroutine 启动的 loop()
函数的任何函数调用(包括内置 append()
),我也明确设置 GOMAXPROCS=1
根据documentation :
limits the number of operating system threads that can execute user-level Go code simultaneously.
然而,在输出中我仍然看到消息 Main
/Goroutine 1
/Goroutine 2
交错,表示以下之一:
GOMAXPROCS
没有像文档,启动更多操作系统线程来安排 goroutine。answer不完整,或者自 2016 年以来发生了一些变化(我在 Go 1.13.5 和 1.15.2 上测试过)。
如果问题得到了回答,我很抱歉,但我既没有找到关于为什么这个特定示例产生控制的解释,也没有找到 goroutine 通常产生控制的点(阻塞系统调用除外)。
注意:这个问题纯粹是理论性的,我现在不打算解决任何实际任务,但总的来说,我假设知道 goroutine 可以让步的点和不能让我们避免重复使用的点同步原语。
最佳答案
引入了 Go 版本 1.14 asynchronous preemption:
Goroutines are now asynchronously preemptible. As a result, loops without function calls no longer potentially deadlock the scheduler or significantly delay garbage collection. This is supported on all platforms except
windows/arm
,darwin/arm
,js/wasm
, andplan9/*
.
如 Are channel sends preemption points for goroutine scheduling? 中的回答, Go 的抢占点可能会从一个版本到下一个版本发生变化。异步抢占只是在几乎所有地方添加可能的抢占点。
您对 output
数组的写入不同步并且您的 oi
索引不是原子的,这意味着我们无法真正确定输出会发生什么大批。当然,用互斥锁给它增加原子性会引入协作调度点。虽然这些不是协作调度切换的来源(这必须根据您的输出发生),但它们确实会扰乱我们对程序的理解。
output
数组保存字符串,使用字符串可以调用垃圾回收系统,垃圾回收系统可以使用锁并引起调度切换。因此,这是 Go-1.14 之前的实现中调度切换的最可能原因。
关于go - goroutine 在什么时候可以 yield?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64113394/
function* generatorFunction() { yield (yield 1)(yield 2)(yield 3)(); } var iterator = generatorFun
ECMAScript 6 应该带来生成器函数和迭代器。生成器函数(具有 function* 语法)返回一个迭代器。迭代器有一个 next 方法,当重复调用时,该方法会执行生成器函数的主体,并在每个 y
ECMAScript 6 应该引入生成器函数和迭代器。生成器函数(具有 function* 语法)返回迭代器。迭代器有一个 next 方法,当重复调用时,它会执行生成器函数的主体,在每个 yield
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 2 年前。 Improve t
自 python 2.5 以来,可以将 send()、throw()、close() 放入生成器中。在定义的生成器中,可以通过执行以下操作来“捕获”发送的数据: def gen(): whil
return的区别和 yield似乎很清楚,直到我发现还有 yield from以及将两者结合起来的可能性 return和 yield在完全相同的功能! 我对return的理解之后的一切都是 不是 执
假设我有这个部分,我正在尝试渲染 #layouts/_subheader.html.erb 当我在这样的 View 中使用这个部分时 Content For Yield
yield操作符是由编译器在底层实现的,该编译器生成一个实现符合 IEnumerable 的状态机的类。和 IEnumerator . 给定一个罗斯林 MethodDeclarationSyntax
$item) echo "$index $item" . PHP_EOL; } resolve(generator1()); echo PHP_EOL; resolve(gener
这个问题在这里已经有了答案: Why converting list to set is faster than converting generator to set? (1 个回答) List c
是否有一个单行代码来获取生成器并生成该生成器中的所有元素?例如: def Yearly(year): yield YEARLY_HEADER for month in range(1, 13)
刚发现yield from 结构,在我看来这有点像反向的yield,而不是从生成器中获取对象,您插入/将对象发送到生成器。喜欢: def foo(): while True:
考虑以下代码: def mygen(): yield (yield 1) a = mygen() print(next(a)) print(next(a)) 输出产量: 1 None 解释器
Guido van Rossum,在 2014 年关于 Tulip/Asyncio 的演讲中 shows the slide : Tasks vs coroutines Compare: res =
谁能帮我理解“yield self”和“yield”的区别? class YieldFirstLast attr_accessor :first, :last def initiali
这是我目前使用 Laravel 5 实现的 Open Graph 标签: app.blade.php @yield('title') page.blade.php @extends('app'
在 Tornado 中,我们通常会编写如下代码来异步调用函数: class MainHandler(tornado.web.RequestHandler): @tornado.gen.coro
本文整理了Java中aQute.bnd.indexer.analyzers.Yield.yield()方法的一些代码示例,展示了Yield.yield()的具体用法。这些代码示例主要来源于Github
我们有超过 100 个共同基金的每日返回,我们希望将这些返回转换为月度返回。每月返回不应是每个月的平均值,而是每个月末的资金返回。基金在不同的时间点开始和结束,它们需要自己保留(不是每个月的共同基金
如何实现 C# yield return使用 Scala 延续?我希望能够编写 Scala Iterator s 风格相同。在 this Scala news post 的评论中有刺伤,但它不起作用(
我是一名优秀的程序员,十分优秀!