我怎样才能生成依赖于它们的前辈的例程?
How can I spawn go routines that depend on their predecessors?
例如,我要填充此矩阵:
| 0 | 0 | 0 | 0 |
| 0 | 1 | 2 | 3 |
| 0 | 2 | 3 | 4 |
| 0 | 3 | 4 | 5 |
具体来说,我想填充它以便每个单元格都遵循规则,
在英语中,单元格的值比其 top
、left
和 topleft
邻居值的最大值大一。
因为每个单元格只有三个依赖项(它的 top
、left
和 topleft
邻居),我可以填充位于 m[1][1]
的单元格(1
),填充后,我可以填充标记为 2
的单元格,因为它们的所有依赖项都已填充。
| 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | ---\ | 0 | 1 | 2 | 0 |
| 0 | 0 | 0 | 0 | ---/ | 0 | 2 | 0 | 0 |
| 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 |
我如何启动 1 个 go routine,然后是 2,然后是 3,然后是 4...,来填充这个矩阵的每个对角线?也许更具体地说,我如何才能在开始依赖单元格之前等待邻居完成?
[编辑]:感谢@Zippoxer 的评论!为了澄清,我问的是 Go to 运行 a go-routine that depends on another finishing first 中的语法是什么。因为当一个go-routine完成时可以启动多个新的go-routines,所以它不是简单的调用没有并发的事情!
使用channels.
一个 goroutine 正在等待另一个 goroutine:
done := make(chan bool)
go func() {
// Work...
done <- true // Signal we're done.
}()
go func() {
<- done // Wait for the previous goroutine to signal.
// Work...
}()
希望这是一个人为的例子,因为这绝对不是最快的解决方案,但也许这就是您想要的。
每个cell运行在自己的goroutine中,有自己的channel,大致代表了它的依赖关系。一旦从其通道读取三个值,单元就会知道其依赖关系已全部解决。当一个单元格完成时,它会将一些值传递给其所有依赖项的通道。
import "sync"
type empty struct{}
func contrivedMathThing(i, j int) ([][]int) {
var wg sync.WaitGroup
wg.Add(i * j)
// Make two-dimensional slices for the channels that the goroutines will
// wait on, and for the results of each cell. Two dimensional slices are
// more annoying to make, but I think make the example a bit more clear.
chans := make([][]chan empty, i)
results := make([][]int, i)
for a := 0; a < i; a++ {
chans[a] = make([]chan empty, j)
results[a] = make([]int, j)
for b := 0; b < j; b++ {
chans[a][b] = make(chan empty, 3)
}
}
for a := 0; a < i; a++ {
for b := 0; b < j; b++ {
go func(a, b int, waitc <-chan empty) {
defer wg.Done()
// Wait for all dependencies to complete
<-waitc
<-waitc
<-waitc
// Compute the result
// Too lazy to write...
// Save the result to the results array
results[a][b] = result
// Signal all dependents that one of their dependencies has
// resolved
if a < i - 1 {
chans[a + 1][b] <- empty{}
}
if b < j - 1 {
chans[a][b + 1] <- empty{}
}
if a < i - 1 && b < j - 1 {
chans[a + 1][b + 1] <- empty{}
}
}(a, b, chans[a][b])
}
}
// All cells in the first row and first column need to start out with two
// of their dependencies satisfied.
for a := 1; a < i; a++ {
chans[a][0] <- empty{}
chans[a][0] <- empty{}
}
for b := 1; b < j; b++ {
chans[0][b] <- empty{}
chans[0][b] <- empty{}
}
// Unblock the cell at [0][0] so this show can get started
close(chans[0][0])
wg.Wait()
return results
}
例如,我要填充此矩阵:
| 0 | 0 | 0 | 0 |
| 0 | 1 | 2 | 3 |
| 0 | 2 | 3 | 4 |
| 0 | 3 | 4 | 5 |
具体来说,我想填充它以便每个单元格都遵循规则,
在英语中,单元格的值比其 top
、left
和 topleft
邻居值的最大值大一。
因为每个单元格只有三个依赖项(它的 top
、left
和 topleft
邻居),我可以填充位于 m[1][1]
的单元格(1
),填充后,我可以填充标记为 2
的单元格,因为它们的所有依赖项都已填充。
| 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | ---\ | 0 | 1 | 2 | 0 |
| 0 | 0 | 0 | 0 | ---/ | 0 | 2 | 0 | 0 |
| 0 | 0 | 0 | 0 | | 0 | 0 | 0 | 0 |
我如何启动 1 个 go routine,然后是 2,然后是 3,然后是 4...,来填充这个矩阵的每个对角线?也许更具体地说,我如何才能在开始依赖单元格之前等待邻居完成?
[编辑]:感谢@Zippoxer 的评论!为了澄清,我问的是 Go to 运行 a go-routine that depends on another finishing first 中的语法是什么。因为当一个go-routine完成时可以启动多个新的go-routines,所以它不是简单的调用没有并发的事情!
使用channels.
一个 goroutine 正在等待另一个 goroutine:
done := make(chan bool)
go func() {
// Work...
done <- true // Signal we're done.
}()
go func() {
<- done // Wait for the previous goroutine to signal.
// Work...
}()
希望这是一个人为的例子,因为这绝对不是最快的解决方案,但也许这就是您想要的。
每个cell运行在自己的goroutine中,有自己的channel,大致代表了它的依赖关系。一旦从其通道读取三个值,单元就会知道其依赖关系已全部解决。当一个单元格完成时,它会将一些值传递给其所有依赖项的通道。
import "sync"
type empty struct{}
func contrivedMathThing(i, j int) ([][]int) {
var wg sync.WaitGroup
wg.Add(i * j)
// Make two-dimensional slices for the channels that the goroutines will
// wait on, and for the results of each cell. Two dimensional slices are
// more annoying to make, but I think make the example a bit more clear.
chans := make([][]chan empty, i)
results := make([][]int, i)
for a := 0; a < i; a++ {
chans[a] = make([]chan empty, j)
results[a] = make([]int, j)
for b := 0; b < j; b++ {
chans[a][b] = make(chan empty, 3)
}
}
for a := 0; a < i; a++ {
for b := 0; b < j; b++ {
go func(a, b int, waitc <-chan empty) {
defer wg.Done()
// Wait for all dependencies to complete
<-waitc
<-waitc
<-waitc
// Compute the result
// Too lazy to write...
// Save the result to the results array
results[a][b] = result
// Signal all dependents that one of their dependencies has
// resolved
if a < i - 1 {
chans[a + 1][b] <- empty{}
}
if b < j - 1 {
chans[a][b + 1] <- empty{}
}
if a < i - 1 && b < j - 1 {
chans[a + 1][b + 1] <- empty{}
}
}(a, b, chans[a][b])
}
}
// All cells in the first row and first column need to start out with two
// of their dependencies satisfied.
for a := 1; a < i; a++ {
chans[a][0] <- empty{}
chans[a][0] <- empty{}
}
for b := 1; b < j; b++ {
chans[0][b] <- empty{}
chans[0][b] <- empty{}
}
// Unblock the cell at [0][0] so this show can get started
close(chans[0][0])
wg.Wait()
return results
}