gpt4 book ai didi

go - 使用golang channel 缺少数据

转载 作者:IT王子 更新时间:2023-10-29 02:22:07 25 4
gpt4 key购买 nike

我遇到了一个奇怪的问题。脚本如下。

package main

import (
"fmt"
"sync"
)

type Data struct {
data []int
}

func main() {
ws := 5
ch := make(chan *Data, ws)
var wg sync.WaitGroup
for i := 0; i < ws; i++ {
wg.Add(1)
go func(wg *sync.WaitGroup, ch chan *Data) {
defer wg.Done()
for {
char, ok := <-ch
if !ok {
return
}
fmt.Printf("Get: %d\n", len(char.data))
}
}(&wg, ch)
}
var d Data
ar := []int{1}
for i := 0; i < ws; i++ {
d.data = []int{}
for j := 0; j < 1000; j++ {
d.data = append(d.data, ar[0])
}
ch <- &d
// time.Sleep(time.Second / 1000) // When this line is moved, a number of data by put and get becomes same.
fmt.Printf("Put: %d\n", len(d.data))
}
close(ch)
wg.Wait()
}

这是运行,预期结果如下。 “Put”和“Get”的数据个数相同。

Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000

但是,不可能每次都得到这个结果。结果如下。每次“Put”和“Get”的数据个数都不一样。

尝试 1

Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000

尝试 2

Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 1000
Put: 1000
Get: 16
Put: 1000
Get: 0

尝试 3

Get: 1000
Put: 1000
Put: 1000
Get: 1
Put: 1000
Get: 1000
Put: 1000
Get: 1
Put: 1000
Get: 1000

尽管在我的 PC 上,“Put”和“Get”的数据数量每次都不同,但在 play.golang.org 上,这两个数据的数量总是相同的。 https://play.golang.org/p/QFSuZmZk7d为什么?

如果在脚本中使用了time.Sleep(time.Second/1000),则两个数据的个数相同。如果你知道这个问题,请你教我。非常感谢您抽出宝贵时间。

最佳答案

您观察到的是“数据竞赛”的一个例子。

当您同时访问同一 block 数据时(至少其中一个是写入),就会发生这种情况。

您每次都引用相同的结构。接下来可能发生的是少数几种可能性之一:

  1. 它在你改变它之前在 channel 的另一边被读取(“预期的”场景)

  2. 你在它被阅读之前就开始变异它。在这种情况下,接收器可以读取任意数量的 Data.data 项,从 0 到 1000,具体取决于读取发生的确切时间。

这个问题有多种解决方案:

  1. 您可以在每次迭代中创建 Data 的新实例。为此,只需将 var d Data 声明移动到循环体内即可。在这种情况下,每次迭代都会创建一个新结构,因此您可能不会错误地改变前一个结构。

  2. 您可以声明 Data 的 channel (结构,而不是指向结构的指针):chan Data。在这种情况下,Data 实例在您每次将它发送到 channel 时都会被隐式复制(因为 Go 中的所有内容都是按值传递的,在赋值时复制)。

关于go - 使用golang channel 缺少数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43063444/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com