doubi1928 2017-03-28 07:40
浏览 8
已采纳

使用Golang频道缺乏资料

I encountered a strange problem. The script is below.

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
", 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
", len(d.data))
    }
    close(ch)
    wg.Wait()
}

This is run, a following result is expected. The number of data for "Put" and "Get" is same.

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

But, this result cannot be got every time. The results are below. The number of data of "Put" and "Get" is different for every time.

Try 1

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

Try 2

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

Try 3

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

ALthough on my PC, the number of data of "Put" and "Get" is different for every time, at play.golang.org, the number of both data is always same. https://play.golang.org/p/QFSuZmZk7d Why?

If time.Sleep(time.Second / 1000) is used in the script, the number of both data becomes same. If you know about this problem, will you please teach me. Thank you so much for your time.

  • 写回答

2条回答 默认 最新

  • dqotv26286 2017-03-28 09:21
    关注

    What you observe is an example of "data race".

    It happens when you concurrently access the same piece of data (with at least one of those being a write).

    You put a reference to the same structure every time. And what may happen next is one of few possibilities:

    1. it was read on the other side of the channel before you mutated it (the "expected" scenario)

    2. you started mutating it before it was read. In this case the receiver may read any number of Data.data items, from 0 to 1000, depending on when exactly the read happened.

    There are multiple solutions for the problem:

    1. You may create the new instance of Data every iteration. For that simply move the var d Data declaration inside the loop body. In this case every iteration a new structure is created, so you may not mutate the previous one by mistake.

    2. You may declare channel of Data (the structures, not pointers to a structure): chan Data. In this case the Data instance is implicitly copied every time you send it to the channel (since everything in Go is passed by value, copied on assignment).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分