两个 goroutine 之间的数据竞争

对于以下代码:


阅读器.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()


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


如何解决此错误?


皈依舞
浏览 142回答 1
1回答

倚天杖

您将一个变量的地址从一个 goroutine 发送到另一个,然后从两个 goroutine 读取/写入该变量,即object.解决方案是作为值传递object,或者为阅读器中的每次迭代重新定义对象。在阅读器的当前实现中,object定义在启动 goroutine 的函数中。似乎没有理由这样做。只需object在 goroutine 的 for 循环中声明即可。go func() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;....&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var object data.InputData&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jsonErr := json.Unmarshal(byteBuffer[:n], &object)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;objCh <- &object&nbsp; &nbsp; }}()或者:go func() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;....&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jsonErr := json.Unmarshal(byteBuffer[:n], &object)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;objCh <- object&nbsp; &nbsp; }}()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go