sync.RWMutex.Lock
Метод sync.RWMutex.Lock применяется для захвата блокировки на запись.
Если блокировка уже удерживается другим писателем или есть активные читатели
(вызвавшие RLock), то вызов Lock будет заблокирован до тех пор,
пока все читатели не освободят мьютекс.
Этот метод гарантирует, что только одна горутина может изменять данные в
критической секции одновременно.
Синтаксис
func (rw *RWMutex) Lock()
Метод не принимает параметров и не возвращает значений.
После вызова Lock горутина получает монопольное право на запись.
Для освобождения блокировки используется метод Unlock.
Пример использования с одной горутиной
Давайте заблокируем RWMutex для записи и изменим общий счетчик:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.RWMutex
counter := 0
mu.Lock()
counter++
mu.Unlock()
fmt.Println(counter)
}
Результат выполнения кода:
1
В этом примере мы безопасно инкрементируем счетчик, защищая его от одновременного доступа.
Пример с несколькими горутинами
Рассмотрим ситуацию, когда несколько писателей конкурируют за запись:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.RWMutex
counter := 0
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(counter)
}
Результат выполнения кода:
5
Каждая горутина захватывает блокировку на запись,
инкрементирует счетчик и освобождает ее. Благодаря
мьютексу итоговое значение всегда равно 5.
Пример с читателями и писателями
Покажем, что Lock ожидает освобождения читателей:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var mu sync.RWMutex
data := "initial"
// Читатель захватывает RLock
go func() {
mu.RLock()
defer mu.RUnlock()
fmt.Println("Reader: data =", data)
time.Sleep(100 * time.Millisecond)
}()
time.Sleep(10 * time.Millisecond)
// Писатель пытается захватить Lock
mu.Lock()
data = "updated"
mu.Unlock()
fmt.Println("Writer: data updated")
}
Результат выполнения кода:
"Reader: data = initial"
"Writer: data updated"
Писатель ждет завершения читателя, затем обновляет данные.
Смотрите также
-
метод
sync.RWMutex.Unlock,
который освобождает блокировку на запись -
метод
sync.RWMutex.RLock,
который захватывает блокировку на чтение -
метод
sync.Mutex.Lock,
который аналогичен для обычного мьютекса -
метод
sync.RWMutex.TryLock,
который пытается захватить блокировку без блокировки