I have one writer goroutine and multiple reader goroutines. I want to block readers when writer is changing data.
package main
data []int
func main() {
m := sync.Mutex{}
for i := 0; i< 10; i++ {
go func reader() {
for {
m.Lock()
myData := data
m.Unlock()
read_from_data(myData)
}
}()
}
go func writer() {
for {
newData := new_data()
m.Lock()
data = newData
m.Unlock()
time.Sleep(1 * time.Seconds)
}
}
}
How can i do this without readers blocking each other?
This is what sync.RWMutex
is for.
It has 2 different lock methods: RWMutex.Lock()
for writers, and RWMutex.RLock()
for readers. (And there are 2 different unlock methods, matching the different lock methods: RWMutex.Unlock()
and RWMutex.RUnlock()
.)
RWMutex
allows multiple readers, or 1 writer. If a writer obtained the lock, no readers are allowed until the writer unlocks (also, no other writers allowed). If a reader obtains the read-lock, any other readers are allowed (but not a writer, not until all readers unlock).
m := sync.RWMutex{}
for i := 0; i < 10; i++ {
go func() { // reader
for {
m.RLock()
myData := data
m.RUnlock()
read_from_data(myData)
}
}()
}
go func() { // writer
for {
newData := new_data()
m.Lock()
data = newData
m.Unlock()
time.Sleep(1 * time.Seconds)
}
}