Чтение и запись в Go
Когда общие данные часто читают и редко меняют, обычный замок держит очередь даже для простого просмотра. Замок чтения и записи разрешает нескольким читателям заходить вместе, а писатель ждет, пока все чтение не закончится, и блокирует и чтение, и запись на время своей работы.
Тип sync.RWMutex используют так же,
как обычный замок, но для чтения берут
RLock и RUnlock, а для изменения
данных по-прежнему Lock и Unlock.
Отпуск в отложенной функции остается
удобным правилом.
Несколько читателей и один писатель:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.RWMutex
var value int = 10
var wg sync.WaitGroup
wg.Add(3)
go func() {
defer wg.Done()
mu.RLock()
defer mu.RUnlock()
fmt.Println("read", value)
}()
go func() {
defer wg.Done()
mu.RLock()
defer mu.RUnlock()
fmt.Println("read", value)
}()
go func() {
defer wg.Done()
mu.Lock()
defer mu.Unlock()
value = 20
fmt.Println("write", value)
}()
wg.Wait()
}
Две ветки с RLock могут печатать
параллельно, пока не начнется захват
на запись. Писатель не войдет, пока
активны читатели; новые читатели не
начнутся, пока писатель держит замок.
Чтение без записи в теле:
package main
import (
"fmt"
"sync"
)
func readVal(v *int, mu *sync.RWMutex, wg *sync.WaitGroup) {
defer wg.Done()
mu.RLock()
defer mu.RUnlock()
fmt.Println(*v)
}
func main() {
var mu sync.RWMutex
n := 5
var wg sync.WaitGroup
wg.Add(2)
go readVal(&n, &mu, &wg)
go readVal(&n, &mu, &wg)
wg.Wait()
}
Дан следующий код:
var mu sync.RWMutex
var score int = 7
func show(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println(score)
}
Оформите show как безопасное
чтение score и запустите три
ветки с ожиданием группы.
Дан следующий код:
var mu sync.RWMutex
var n int
func set(v int) {
mu.Lock()
n = v
}
Допишите отпуск замка и скажите, может
ли в этот момент параллельно идти
чтение через RLock.
Скажите, когда вместо обычного замка имеет смысл взять замок чтения и записи.