我是 GoLang 的学习者,正在尝试试验和学习同步包和 chan 概念。
Follwoing 是我正在运行并期望在控制台上打印 Receiving Channel Value 的代码,但是该值没有被打印出来,它有时会打印这些值,但并非总是如此。
如果我遍历 chan 而没有将它放入 go 例程中,那么它会打印所有 channel 值但失败并出现错误“fatal error: all goroutines are sleep - deadlock!”
我尝试使用 channel “完成”同步 channel 读取,但在那种情况下它再次开始失败并出现相同的错误。我也尝试了 waitGroup API,您可以在我的代码中看到它(已注释),但这对我也不起作用。
感谢帮助
源代码:
package main
import (
"fmt"
"sync"
)
type safeOperation struct {
i int
sync.Mutex
}
var wg sync.WaitGroup
func main() {
so := new(safeOperation)
ch := make(chan int)
//done := make(chan bool)
for i := 0; i < 5; i++ {
go so.Increment(ch)
go so.Decrement(ch)
}
go func() {
//wg.Add(1)
for c := range ch {
fmt.Println("Receiving Channel Value: ", c)
}
//wg.Done()
//done <- true
}()
//wg.Wait()
//<-done
fmt.Println("Value: ", so.GetValue())
fmt.Println("Main method finished")
}
func (so *safeOperation) Increment(ch chan int) {
//so.Lock()
//defer wg.Done()
so.i++
ch <- so.i
//so.Unlock()
}
func (so *safeOperation) Decrement(ch chan int) {
//so.Lock()
//defer wg.Done()
so.i--
ch <- so.i
//so.Unlock()
}
func (so *safeOperation) GetValue() int {
so.Lock()
v := so.i
so.Unlock()
return v
}
输出: 值:1 主要方法完成
最佳答案
使用 WaitGroup
的一个好模式是在发送到 channel 之前调用 Add()
或使用 go
关键字,然后调用Done()
从 channel 接收后。
通过这种方式,您可以确保 Add()
始终被及时调用,无论是否在 channel block 上发送。
我已经更改了您的示例代码来执行此操作:
package main
import (
"fmt"
"sync"
)
type safeOperation struct {
i int
sync.Mutex
}
var wg sync.WaitGroup
func main() {
so := new(safeOperation)
ch := make(chan int)
for i := 0; i < 5; i++ {
wg.Add(1)
go so.Increment(ch)
wg.Add(1)
go so.Decrement(ch)
}
go func() {
for c := range ch {
fmt.Println("Receiving Channel Value: ", c)
wg.Done()
}
}()
wg.Wait()
//<-done
fmt.Println("Value: ", so.GetValue())
fmt.Println("Main method finished")
}
func (so *safeOperation) Increment(ch chan int) {
so.i++
ch <- so.i
}
func (so *safeOperation) Decrement(ch chan int) {
so.i--
ch <- so.i
}
func (so *safeOperation) GetValue() int {
so.Lock()
v := so.i
so.Unlock()
return v
}
当然,您还想用互斥体保护 safeOperation.i
(否则它的值将不可预测),但这就是获得所需输出所必需的。
关于go - 不在控制台上打印接收 channel 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51576115/