【问题标题】:Not printing Receiving Channel value on console不在控制台上打印接收通道值
【发布时间】:2019-01-05 15:36:34
【问题描述】:

我是 GoLang 的学习者,正在尝试尝试和了解 Sync 包和 chan 概念。

以下是我正在运行并希望在控制台上打印接收渠道值的代码,但该值没有被打印出来,它有时会打印这些值,但并非总是如此。

如果我通过 chan 而不将其放入 go 例程中,那么它会打印所有通道值但失败并出现错误“致命错误:所有 goroutines 都处于睡眠状态 - 死锁!

我尝试使用通道“完成”同步通道读取,但在这种情况下,它再次开始失败并出现相同的错误。我还尝试了 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 主方法完成

【问题讨论】:

    标签: go


    【解决方案1】:

    使用WaitGroup 的一个很好的模式是在发送到频道之前调用Add() 或使用go 关键字,并在从频道接收后调用Done()。 这样您就可以确保Add() 始终被按时调用,无论是否在通道上发送阻塞。

    我已更改您的示例代码以执行此操作:

    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
    }
    

    Go playground link

    当然,您还想用互斥体保护safeOperation.i(否则它的值将不可预测),但这就是获得所需输出所必需的全部。

    【讨论】:

      猜你喜欢
      • 2012-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-13
      • 2022-01-08
      • 2023-03-14
      • 2013-06-15
      相关资源
      最近更新 更多