繁体   English   中英

两个 goroutine 之间的数据竞争

[英]data race between two goroutines

对于以下代码:

读者.go

func (r *Reader) ReadData(objCh chan *data.InputEntry, stopCh chan struct{}) {

    var object data.InputEntry

    go func() {
        for {
            ....
            jsonErr := json.Unmarshal(byteBuffer[:n], &object) // Line 55
             ...    
            objCh <- &object
        }

    }()
}

作家.go

func (w *Processor) ProcessData(objectCh chan *data.InputEntry, stopCh chan struct{}) {

    go func() {
        for {
            object, wd := <-objectCh
            ...    
            w.Log.Printf("Received object: %v\n", object) // Line 83


        }
    }()
}

以下是错误:

WARNING: DATA RACE
Write at 0x00c000138000 by goroutine 7:
  reflect.Value.SetString()
      /usr/local/go/src/reflect/value.go:1712 +0xb3
  encoding/json.(*decodeState).literalStore()
      /usr/local/go/src/encoding/json/decode.go:972 +0x3179
  encoding/json.(*decodeState).value()
      /usr/local/go/src/encoding/json/decode.go:401 +0x2dc
  encoding/json.(*decodeState).object()
      /usr/local/go/src/encoding/json/decode.go:782 +0x225e
  encoding/json.(*decodeState).value()
      /usr/local/go/src/encoding/json/decode.go:387 +0xaf
  encoding/json.(*decodeState).unmarshal()
      /usr/local/go/src/encoding/json/decode.go:180 +0x27a
  encoding/json.Unmarshal()
      /usr/local/go/src/encoding/json/decode.go:107 +0x1de
  github.com/myhub/code/reader.(*Reader).ReadData.func1()
      /home/../code/src/github.com/myhub/code/reader/reader.go:55 +0x385

Previous read at 0x00c000138000 by goroutine 8:
  reflect.typedmemmove()
      /usr/local/go/src/runtime/mbarrier.go:177 +0x0
  reflect.packEface()
      /usr/local/go/src/reflect/value.go:119 +0x126
  reflect.valueInterface()
      /usr/local/go/src/reflect/value.go:1023 +0x1b9
  reflect.Value.Interface()
      /usr/local/go/src/reflect/value.go:993 +0x3c27
  fmt.(*pp).printValue()
      /usr/local/go/src/fmt/print.go:726 +0x3c28
  fmt.(*pp).printValue()
      /usr/local/go/src/fmt/print.go:880 +0x2709
  fmt.(*pp).printArg()
      /usr/local/go/src/fmt/print.go:716 +0x25a
  fmt.(*pp).doPrintf()
      /usr/local/go/src/fmt/print.go:1030 +0x311
  fmt.Sprintf()
      /usr/local/go/src/fmt/print.go:219 +0x73
  log.(*Logger).Printf()
      /usr/local/go/src/log/log.go:188 +0x64
  github.com/myhub/code/writer.(*Processor).ProcessData.func1()
      /home/../code/src/github.com/myhub/code/writer/writer.go:83 +0xa5

Goroutine 7 (running) created at:
    github.com/myhub/code/reader.(*Reader).ReadData()
      /home/../code/src/github.com/myhub/code/reader/reader.go:41 +0xb5
  main.main()
      /home/../code/src/github.com/myhub/code/main.go:42 +0x10c

Goroutine 8 (running) created at:
  github.com/myhub/code/writer.(*Processor).ProcessData()
      /home/../code/src/github.com/myhub/code/writer/writer.go:75 +0x60
  main.main()
      /home/../code/src/github.com/myhub/code/main.go:44 +0x12e
==================

数据竞争发生在第 55 行( reader.go )和第 83 行( writer.go )之间

如何解决这个错误?

您正在将一个变量的地址从一个 goroutine 发送到另一个 goroutine,然后从两个 goroutine 读/写该变量,即object

解决方案是将object作为值传递,或者为读取器中的每次迭代重新定义 object。 在阅读器的当前实现中, object定义在 function 启动的 goroutine 中。 似乎没有理由这样做。 只需在 goroutine 的 for 循环中声明object

go func() {
    for {
         ....
         var object data.InputData
         jsonErr := json.Unmarshal(byteBuffer[:n], &object)
             ...    
         objCh <- &object
    }
}()

要么:

go func() {
    for {
         ....
         jsonErr := json.Unmarshal(byteBuffer[:n], &object)
             ...    
         objCh <- object
    }
}()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM