为什么这段代码会产生DATA RACE呢?

baocaixiong · 2021-11-04 21:09:18 · 1734 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2021-11-04 21:09:18 的主题,其中的信息可能已经有所发展或是发生改变。

为什么这段代码会产生DATA RACE呢?

// main.go
package main

import (
    "fmt"
    "log"
    "sync"
    "time"
)

type runner struct {
    mutableCh chan func()
    close     chan struct{}
}

var pool = &sync.Pool{
    New: func() interface{} {
        return new(runner)
    },
}

func newRunner() *runner {
    r := pool.Get().(*runner)
    r.mutableCh = make(chan func())
    r.close = make(chan struct{})
    return r
}

func (r *runner) send(fn func()) error {
    wait := make(chan struct{})

    var err error
    r.mutableCh <- func() {
        defer func() {
            if e := recover(); e != nil {
                log.Printf("%s", e)
                err = fmt.Errorf("error: %s", e)
                close(wait)
            }
        }()

        fn()
        close(wait)
    }

    <-wait
    return err
}

func (r *runner) start() {
    go func() {
        for {
            select {
            case fn := <-r.mutableCh:
                fn()
            case <-r.close:
                return
            }
        }
    }()
}

func (r *runner) stop() {
    close(r.close)
}

func releaserunner(s *runner) {
    s.mutableCh = nil
    s.close = nil
    pool.Put(s)
}

func main() {
    r := newRunner()
    defer releaserunner(r)
    r.start()
    // err1 := r.send(func() {
    //     fmt.Println("send---")
    // })
    // fmt.Println(err1)

    r.stop()
    time.Sleep(time.Second * 1)
}

执行 go run -race main.go

==================
WARNING: DATA RACE
Write at 0x00c00011a220 by main goroutine:
  main.releaserunner()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:71 +0x3e
  main.main()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:87 +0x1b0

Previous read at 0x00c00011a220 by goroutine 7:
  main.(*runner).start.func1()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:53 +0x64

Goroutine 7 (finished) created at:
  main.(*runner).start()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:50 +0x4c
  main.main()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:79 +0x17e
==================
==================
WARNING: DATA RACE
Write at 0x00c00011a228 by main goroutine:
  main.releaserunner()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:72 +0x69
  main.main()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:87 +0x1b0

Previous read at 0x00c00011a228 by goroutine 7:
  main.(*runner).start.func1()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:55 +0x8a

Goroutine 7 (finished) created at:
  main.(*runner).start()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:50 +0x4c
  main.main()
      /home/users/zhangming12/gopath/src/icode.baidu.com/baidu/ps-se-go/exgraph/test.go:79 +0x17e
==================
Found 2 data race(s)
exit status 66

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1734 次点击  
加入收藏 微博
2 回复  |  直到 2022-09-02 17:48:50
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传