У меня есть требование обновить таймер общего объекта в нескольких процедурах go. Но в конечном итоге это состояние гонки. Я не могу использовать блокировку для ожидания на канале, потому что все остальные процедуры должны будут ждать.Несколько ходовых процедур, ожидающих общего таймера, вызывающего гонку
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
}
}
когда я бегу с помощью
go run -race thread.go
это дает
==================
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
==================
и вешает
любая помощь будет полезна
Просто защитите параллельные записи в 'R.timer' с помощью' sync.Mutex', для чего они предназначены. – Volker
даже если я эта гонка все еще происходит. между записью и ожиданием канала. тип Р { структура таймера * time.Timer // другие поля м sync.Mutex } FUNC F (сделано чан BOOL, R * R) { \t rmLock() r.timer = время. NewTimer (time.Millisecond * time.Duration (1000 + rand.Intn (2))) rmUnlock() // некоторый код, одновременно обращающийся к другим полям общего объекта r, не может помещать блокировку здесь <-r. timer.C done <- true } –
Если вы не хотите использовать Mutex/locks, то идиоматическим способом является обмен информацией по каналам. Вы можете просто передать другой канал в свой метод и отправить значения, которые вы хотите обновить. После запуска goroutines у вас есть выбор или выбор в цикле, где вы обновляете свой экземпляр 'R' в неконкурентном контексте. – evanmcdonnal