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

baocaixiong · · 1606 次点击
jan-bar
想要拥有,必定付出。
改了下你的程序,在看到你这个问题之前我都没这么敲过命令都不知道`DATA RACE`,但是我花了几分钟研究了一下,下面是我改后的代码。只要确保变量不会同时出现在两个协程就行。上面虽然关闭了close的通道,但是程序执行很快的,所以两个变量可能存在竞争吧。 ```go // main.go package main import ( "fmt" "log" "sync" "time" ) type runner struct { mutableCh chan func() close chan struct{} ok 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{}) r.ok = 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: r.ok <- struct{}{} return } } }() } func (r *runner) stop() { close(r.close) } func releaserunner(s *runner) { <-s.ok 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) } ```
#1