Метод sync.RWMutex.RLock
Метод sync.RWMutex.RLock захватывает блокировку для чтения.
Он позволяет множеству горутин одновременно читать защищенные данные,
но блокирует запись до тех пор, пока все блокировки чтения не будут
освобождены. В отличие от Lock, метод RLock не блокирует
другие операции чтения, что делает его эффективным для сценариев
с частым чтением и редкой записью.
Метод не принимает никаких параметров и не возвращает значений.
После вызова RLock необходимо обязательно вызвать метод
RUnlock для освобождения блокировки чтения, чтобы избежать
взаимных блокировок.
Синтаксис
var mu sync.RWMutex
mu.RLock()
// чтение защищенных данных
mu.RUnlock()
Пример
Давайте рассмотрим пример чтения данных с использованием блокировки для чтения:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.RWMutex
data := make(map[string]int)
// Запись данных
mu.Lock()
data["counter"] = 42
mu.Unlock()
// Чтение данных
mu.RLock()
res := data["counter"]
mu.RUnlock()
fmt.Println(res)
}
Результат выполнения кода:
42
Пример
Давайте продемонстрируем, что множество горутин могут
одновременно читать данные с помощью RLock:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var mu sync.RWMutex
counter := 0
var wg sync.WaitGroup
reader := func(id int) {
defer wg.Done()
mu.RLock()
fmt.Printf("Reader %d reads: %d\n", id, counter)
time.Sleep(100 * time.Millisecond)
mu.RUnlock()
}
for i := 0; i < 5; i++ {
wg.Add(1)
go reader(i)
}
wg.Wait()
}
Результат выполнения кода:
"Reader 4 reads: 0"
"Reader 2 reads: 0"
"Reader 1 reads: 0"
"Reader 0 reads: 0"
"Reader 3 reads: 0"
Пример
Давайте рассмотрим ситуацию, когда операция записи ожидает освобождения блокировок чтения:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var mu sync.RWMutex
counter := 0
var wg sync.WaitGroup
reader := func(id int) {
defer wg.Done()
mu.RLock()
fmt.Printf("Reader %d acquired read lock\n", id)
time.Sleep(200 * time.Millisecond)
fmt.Printf("Reader %d released read lock\n", id)
mu.RUnlock()
}
writer := func() {
defer wg.Done()
fmt.Println("Writer waiting for write lock")
mu.Lock()
counter++
fmt.Println("Writer acquired write lock")
mu.Unlock()
}
for i := 0; i < 3; i++ {
wg.Add(1)
go reader(i)
}
time.Sleep(50 * time.Millisecond)
wg.Add(1)
go writer()
wg.Wait()
}
Результат выполнения кода:
"Reader 2 acquired read lock"
"Reader 1 acquired read lock"
"Reader 0 acquired read lock"
"Writer waiting for write lock"
"Reader 2 released read lock"
"Reader 1 released read lock"
"Reader 0 released read lock"
"Writer acquired write lock"
Смотрите также
-
метод
sync.RWMutex.RUnlock,
который освобождает блокировку чтения -
метод
sync.RWMutex.Lock,
который захватывает блокировку для записи -
метод
sync.RWMutex.TryRLock,
который пытается захватить блокировку чтения без блокировки -
тип
sync.RWMutex,
который предоставляет механизм блокировки для чтения и записи