sync.RWMutex.TryLock
Метод sync.RWMutex.TryLock выполняет попытку захвата блокировки на запись для мьютекса типа RWMutex. Если блокировка на запись в данный момент свободна и нет активных блокировок на чтение, то метод захватывает ее и возвращает true. В противном случае, если блокировка уже занята другой горутиной на запись или есть активные читатели, метод немедленно возвращает false, не блокируя выполнение текущей горутины. Этот метод полезен для реализации неблокирующих операций записи, когда критическая секция должна выполняться только при отсутствии конкуренции.
Синтаксис
func (rw *RWMutex) TryLock() bool
Метод не принимает никаких параметров и возвращает логическое значение bool: true, если блокировка на запись успешно захвачена, и false, если захватить блокировку не удалось.
Пример
Давайте рассмотрим базовый пример использования метода TryLock для безопасной попытки записи в общую структуру данных:
package main
import (
"fmt"
"sync"
"time"
)
type Counter struct {
mu sync.RWMutex
value int
}
func (c *Counter) TryIncrement() bool {
if c.mu.TryLock() {
c.value++
c.mu.Unlock()
return true
}
return false
}
func (c *Counter) Value() int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.value
}
func main() {
counter := &Counter{}
// Захватываем блокировку на запись в отдельной горутине
go func() {
counter.mu.Lock()
time.Sleep(2 * time.Second)
counter.value = 100
counter.mu.Unlock()
}()
time.Sleep(100 * time.Millisecond)
// Пытаемся захватить блокировку на запись
if counter.TryIncrement() {
fmt.Println("counter incremented successfully")
} else {
fmt.Println("counter is locked, try again later")
}
// Ждем завершения горутины и проверяем значение
time.Sleep(2 * time.Second)
fmt.Printf("final counter value: %d\n", counter.Value())
}
Результат выполнения кода:
"counter is locked, try again later"
"final counter value: 100"
В этом примере горутина захватывает блокировку на запись на 2 секунды. Попытка вызова TryLock в основной горутине сразу возвращает false, так как блокировка уже занята.
Пример
Рассмотрим ситуацию, когда метод TryLock успешно захватывает блокировку, так как нет активных читателей или писателей:
package main
import (
"fmt"
"sync"
)
type DataStore struct {
mu sync.RWMutex
data map[string]int
}
func (ds *DataStore) TryWrite(key string, value int) bool {
if ds.mu.TryLock() {
ds.data[key] = value
ds.mu.Unlock()
return true
}
return false
}
func main() {
store := &DataStore{
data: make(map[string]int),
}
// Успешная попытка записи
if store.TryWrite("count", 42) {
fmt.Println("write successful")
} else {
fmt.Println("write failed")
}
// Проверяем результат
store.mu.RLock()
fmt.Printf("data: %v\n", store.data)
store.mu.RUnlock()
}
Результат выполнения кода:
"write successful"
"data: map[count:42]"
В этом примере метод TryLock успешно захватывает блокировку, так как мьютекс свободен, и выполняет запись в карту.
Пример
Покажем, что метод TryLock не блокируется, если есть активные блокировки на чтение:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var rwmu sync.RWMutex
// Захватываем блокировку на чтение
rwmu.RLock()
fmt.Println("read lock acquired")
// Пытаемся захватить блокировку на запись
if rwmu.TryLock() {
fmt.Println("write lock acquired")
rwmu.Unlock()
} else {
fmt.Println("write lock not acquired - read lock active")
}
// Освобождаем блокировку на чтение
rwmu.RUnlock()
fmt.Println("read lock released")
// Теперь пытаемся снова
if rwmu.TryLock() {
fmt.Println("write lock acquired successfully")
rwmu.Unlock()
} else {
fmt.Println("write lock not acquired")
}
}
Результат выполнения кода:
"read lock acquired"
"write lock not acquired - read lock active"
"read lock released"
"write lock acquired successfully"
Метод TryLock не может захватить блокировку на запись, пока активна хотя бы одна блокировка на чтение, и возвращает false, не блокируя выполнение.
Смотрите также
-
метод
sync.RWMutex.RLock,
который захватывает блокировку на чтение -
метод
sync.RWMutex.Lock,
который захватывает блокировку на запись с блокировкой -
метод
sync.RWMutex.TryRLock,
который выполняет неблокирующую попытку захвата блокировки на чтение -
тип
sync.RWMutex,
который предоставляет механизм читатель-писатель мьютекса