多个执行例程等待共享计时器导致比赛

I have a requirement to update timer of a shared object in multiple go routines. But it end up with race condition. I cannot use lock for waiting on the channel because all the other routines will have to wait.

package main
import( 
    "time"
    "math/rand"
)
type R struct {
    timer *time.Timer
    //other fields
}

func f(done chan bool,r *R){
    r.timer =time.NewTimer(time.Millisecond * time.Duration(1000 + rand.Intn(2)))
    //some code simultaneously accessing other fields of shared object r, cannot put a lock here
    <-r.timer.C

    done <- true
}

func main(){
    done := make(chan bool , 5)
    var r *R
    var t *time.Timer
    r = &R{timer:t}
    for i:=0;i<5;i++{
        go f(done,r)
    }
    for i:=0;i<5;i++{
        <-done
    }
}

when I run using

 go run -race thread.go

it gives

==================

WARNING: DATA RACE
Write by goroutine 5:
  main.f()
      usr/local/gocode/thread.go:12 +0x69

Previous write by goroutine 4:
  main.f()
      usr/local/gocode/thread.go:12 +0x69

Goroutine 5 (running) created at:
  main.main()
      usr/local/gocode/thread.go:25 +0xd3

Goroutine 4 (running) created at:
  main.main()
      usr/local/gocode/thread.go:25 +0xd3
==================

and hangs

any help would be useful

There is a design issue here - you have one R object, and it has a shared instance, but every goroutine creates a new timer that is local. Seems to me like you need a local timer per goroutine, and not share that timer between all of them, it just doesn't make sense.

If you rewrite your code like so:

type R struct {
    //other fields
    Foo string
    Bar interface{}
}

func f(done chan bool, r *R) {
    timer := time.NewTimer(time.Millisecond * time.Duration(1000+rand.Intn(2)))
    //some code simultaneously accessing other fields of shared object r, cannot put a lock here
    <-timer.C

    done <- true
}

the timer becomes local to the goroutine as it should be, and you have no race condition, at least for the timer access.

Note that still, ever access to the shared object's other fields must be protected by a mutex or you'll get the same issue.