我知道goroutine被多路复用到多个OS线程上,因此如果应该阻塞,例如在等待I/O时,其他人继续运行.但有没有办法提前知道如果我要创建n个goroutines我会产生多少个线程?
例如,如果我们调用下面的函数,我们就知道将为n个goroutines创建多少(或最大数量)系统线程:
type Vector []float64
// Apply the operation to n elements of v starting at i.
func (v Vector) DoSome(i, n int, u Vector, c chan int) {
for ; i < n; i++ {
v[i] += u.Op(v[i])
}
c <- 1; // signal that this piece is done
}
Run Code Online (Sandbox Code Playgroud) 到目前为止我见过的所有例子都涉及阻塞以获得结果(通过<-chan运算符).
我当前的方法涉及将指针传递给结构:
type goresult struct {
result resultType;
finished bool;
}
Run Code Online (Sandbox Code Playgroud)
goroutine在完成后写的.然后,finished只要方便,就可以轻松检查.你有更好的选择吗?
我真正的目标是Qt风格的信号槽系统.我有预感,解决方案看起来几乎是微不足道的(chan有许多未探索的潜力),但我还不熟悉这种语言来解决它.
有没有办法确保goroutine只能在特定的OS线程中运行?例如,当GUI操作必须在GUI线程中运行时,可能存在多个运行GUI代码的goroutine.
GOMAXPROCS(1) 在技术上做的工作,但这违背了多线程的目的.
LockOSThread() 也工作,但这也阻止任何其他goroutine在该线程中运行.
有没有办法做到这一点,或者所有需要相同线程的东西也必须在同一个goroutine中运行?
我正在用goroutines做一些测试,只是为了了解它们是如何工作的,但它们似乎根本没有运行.我做了一个非常简单的测试:
package main
import (
"fmt"
)
func test() {
fmt.Println("test")
}
func main() {
go test()
}
Run Code Online (Sandbox Code Playgroud)
我希望这打印"测试",但它根本不做任何事情,没有消息,但也没有错误.我也尝试for {}在程序结束时添加一个,以便给goroutine时间打印一些东西,但这没有帮助.
知道可能是什么问题吗?
我试图解决这个问题的练习:
编写一个程序,使用并行计算计算文本中字母的频率.
基本上,我有一个FreqMap类型:
type FreqMap map[rune]int
Run Code Online (Sandbox Code Playgroud)
和一个Frequency功能:
func Frequency(s string) FreqMap {
m := make(FreqMap)
for _, v := range s {
m[v]++
}
return m
}
Run Code Online (Sandbox Code Playgroud)
Exercism提供了一个使用递归实现并发版本的示例,但我想使用for 循环实现我自己的版本.我提出了以下解决方案,但不起作用:
func ConcurrentFrequency(l []string) FreqMap {
c := make(chan FreqMap)
for i := 0; i < len(l); i++ {
go func(i int) {
c <- Frequency(l[i])
}(i)
}
return <- c
}
Run Code Online (Sandbox Code Playgroud)
这似乎只在1次迭代后返回,c似乎只包含1个goroutine的结果; 如果我添加一个,我会得到相同的结果sync.WaitGroup.
你能解释一下我在这里缺少什么吗?
预先感谢您的帮助!
分段堆栈如何工作?这个问题也适用于Boost.Coroutine我所以我也在使用C++标签.主要的疑问来自这篇文章看起来他们所做的是在堆栈的底部保留一些空间并通过在那里分配的内存(可能通过mmap和mprotect?)注册某种信号处理程序来检查它是否已经损坏了当他们发现他们已经耗尽了空间时,他们继续分配更多的内存,然后从那里继续.3个问题
这不是构建用户空间的东西吗?它们如何控制新堆栈的分配位置以及如何编译程序的指令以了解它?
push指令基本上只是向堆栈指针添加一个值,然后将值存储在堆栈中的寄存器中,那么push指令如何知道新堆栈的启动位置以及相应的pop如何知道它何时必须将堆栈指针移回旧堆栈?
他们也说
在我们得到一个新的堆栈段之后,我们
goroutine通过重试导致我们用完堆栈的函数来重新启动它
这是什么意思?他们重启整个goroutine吗?这不可能导致非确定性行为吗?
他们如何检测到程序已超出堆栈?如果他们在底部保留一个canary-ish内存区域,那么当用户程序创建一个足够大的数组溢出时会发生什么?这不会导致堆栈溢出并且是一个潜在的安全漏洞吗?
如果Go和Boost的实现不同,我很高兴知道它们中的任何一个如何处理这种情况
package main
import "time"
func main() {
i := 1
go func() {
for {
i++
}
}()
<-time.After(1 * time.Second)
println(i)
}
Run Code Online (Sandbox Code Playgroud)
总是输出1.
然而,1s足以让for循环经历多次.
我认为,i在闭包是i在mainFUNC.
请参阅下面的代码.
package main
import "time"
func main() {
i := 1
go func() {
for {
i++
println("+1")
}
}()
<-time.After(1 * time.Second)
println(i)
}
Run Code Online (Sandbox Code Playgroud)
经过多行"+1"后,输出正好符合预期.
我在多个非缓冲通道上使用select时发现了
select {
case <- chana:
case <- chanb:
}
Run Code Online (Sandbox Code Playgroud)
即使两个通道都有数据,但在处理此选择时,如果chana和case chanb处于不平衡的调用.
package main
import (
"fmt"
_ "net/http/pprof"
"sync"
"time"
)
func main() {
chana := make(chan int)
chanb := make(chan int)
go func() {
for i := 0; i < 1000; i++ {
chana <- 100 * i
}
}()
go func() {
for i := 0; i < 1000; i++ {
chanb <- i
}
}()
time.Sleep(time.Microsecond * 300)
acount := 0
bcount := 0
wg := …Run Code Online (Sandbox Code Playgroud) 我编写了一个 API 来进行数据库调用并执行一些业务逻辑。我正在调用一个必须在后台执行某些操作的 goroutine。由于 API 调用不应等待此后台任务完成,因此我在调用 goroutine 后立即返回 200 OK(让我们假设后台任务永远不会给出任何错误。)
我读到,一旦 goroutine 完成其任务,goroutine 将被终止。这种一劳永逸的方式是否能避免 goroutine 泄漏?Goroutine 在执行任务后是否会终止并清理?
func DefaultHandler(w http.ResponseWriter, r *http.Request) {
// Some DB calls
// Some business logics
go func() {
// some Task taking 5 sec
}()
w.WriteHeader(http.StatusOK)
}
Run Code Online (Sandbox Code Playgroud) 让\xe2\x80\x99s 说我使用 aWaitGroup让应用程序的主线程等待,直到我从所述 main 启动的所有 goroutine 完成。
是否有一种安全、直接的方法可以在任何时间点评估有多少与 said 相关的 goroutineWaitGroup仍在运行?