【问题标题】:golang does passing pointer through channel break the csp design?golang 通过通道传递指针会破坏 csp 设计吗?
【发布时间】:2022-01-24 03:13:31
【问题描述】:

下面是我的测试代码

type Data struct {
    data int
}

func printData(c chan *Data) {
    time.Sleep(time.Second * 1)
    data := <-c
    for {
        data.data = 100
    }
}

func main() {
    fmt.Println("Main started...")
    a := Data{data: 1}
    b := &a

    //create channel
    c := make(chan *Data, 10)
    go printData(c)
    fmt.Println(fmt.Printf("Value of b before putting into channel %v", *b))
    c <- b
    for {
        b.data = 20
    }
}

我使用go build -race 构建二进制文件,正如预期的那样发生了数据竞争

我的怀疑是我认为传递指针不正确,因为当使用具有多个 goroutine 的通道时,通道有一个锁,但是一个指向通道的传递指针,导致 goroutine 需要添加另一个锁来保护数据竞争。很奇怪

所以我的理解是对的?

【问题讨论】:

    标签: go


    【解决方案1】:

    你有一个数据竞争,因为两个例程试图使用同一个底层对象而不同步。如果您在创建 goroutine 之前存储了指向共享对象的指针,您将在没有通道的情况下获得相同的比赛。如果在传递指针后,您停止在两个 goroutine 之一中使用底层对象,您将不会竞争。所以问题不是 channel 本身,而是在两个单独的 goroutine 中使用共享的 底层对象

    换句话说,分享方法是不相关的。 有分享的事实才是最重要的。

    CSP 背后的一个想法是通过通信进行共享(即发送需要处理的实际数据),而不是通过共享进行通信(即说服两个可能同时运行的独立顺序处理器在共享数据时表现良好)数据)。

    当数据本身非常大时,发送一个指针——并立即“放弃”底层数据——可能是一个很好的策略,可以降低数据复制的成本。但这是一种优化技术,只有在性能分析表明数据复制是操作中代价高昂的部分之后才应该这样做。添加指针间接会增加性能成本,必须通过降低的通信成本来弥补。在您的特定情况下,要操作的数据由单个 int 值组成,因此增加的指针成本大大超过任何其他减少的成本,您应该只共享数据,如果那是 算法要求。

    【讨论】:

    • 感谢您的回答,在阅读此答案之前我很困惑。 1. CSP 不关心数据 2. 数据竞争不是渠道的问题,其他场景也有问题。 3.策略“放手”,我同意再次感谢:)
    猜你喜欢
    • 2014-01-17
    • 2016-06-09
    • 1970-01-01
    • 2015-03-28
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 2017-12-03
    • 2020-05-14
    相关资源
    最近更新 更多