通过通道进行的Golang字节数组通信丢失数据

huangapple go评论84阅读模式
英文:

Golang byte array communication through channel loses data

问题

我正在使用一个工作-工作者队列实现在我的 Golang 项目中。
WorkRequest 结构如下:

type WorkRequest struct {
    fields map[string][]byte
}

调度器是这样的:

go func() {
    for {
        select {
        case work := <-WorkQueue:
            go func() {
                worker := <-WorkerQueue
                worker.Work <- work
            }()
        }
    }
}()

worker.Work 是 WorkRequest 结构的通道,WorkerQueue 是 Worker 结构的通道。
每当有许多并发请求进入 WorkQueue 时,调度器例程会将其分配给工作者。

我注意到当我向 WorkQueue 发送并发请求时,有些请求被忽略了,有些请求被执行了多次。

例如,如果我将 ID 为 1、2、3、4、5 的工作排队,我会看到工作者获得的工作 ID 是 1、2、4、4、5... 这里的 4 被执行了两次,而 3 被忽略了。当我将 WorkRequest 的字段实现为 map[string]string 而不是 []byte 时,相同的代码运行正常。

我是否遗漏了什么,或者是切片不是线程安全的,导致分配了相同的变量?

英文:

I'm using a work-worker Queue implementation in my golang project.
The WorkRequest Struct is as below

type WorkRequest struct {
fields map[string] []byte }

and the dipatcher is

go func() {
    for {
        select {
        case work := &lt;-WorkQueue:
            go func() {
                worker := &lt;-WorkerQueue
                worker.Work &lt;- work
            }()
        }
    }
}()

The worker.Work is channel for WorkRequest struct and WorkerQueue is channel of Worker struct.
Whenever there are many concurrent requests coming in WorkQueue it gets assigned to worker byt the dispatcher routine.

I'm observing issue when I send concurrent requests to WorkQueue, few of them miss out and few of them get executed multiple times.

e.g. If I've queued works with ID 1, 2, 3, 4, 5... then I see workers getting work with ID 1, 2, 4, 4, 5... here 4 is executed twice and 3 is missed. The same code works fine when I implement WorkRequest fields as map[string]string instead of []byte.

Am I missing something or is slice not thread safe and gets assigned same variable.

答案1

得分: 2

在Go语言中,string是不可变的,所以它可以正常工作,但是所有的切片都是可变的。此外,它们可以共享底层数组。你没有展示相关的代码,但我猜你期望map保存一个切片的副本。一个切片只是内存中的地址和长度。当将切片放入map中时,你需要手动创建一个新的切片并复制其内容。

要修复你的代码,在将切片放入map中时,创建一个切片的副本。

英文:

In Go string is immutable, so it works fine but all slices are mutable. Moreover they can share the backing array. You are not showing the relevant code but I guess you are expecting the map to hold copy of a slice. A slice is just address in memory and length. You need to manually make a new slice and copy its contents.

To fix your code make a copy of slice when putting it into map.

huangapple
  • 本文由 发表于 2017年3月30日 15:57:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/43111772.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定