Lock-free (без блокировок) — это класс алгоритмов и структур данных, которые гарантируют прогресс хотя бы одной из конкурирующих горутин без использования традиционных примитивов синхронизации (мьютексов, RWMutex).
Ключевые характеристики:
// Псевдокод CAS-операции
func CompareAndSwap(addr *int, expected, new int) bool {
if *addr == expected {
*addr = new
return true
}
return false
}
Пакет предоставляет атомарные операции для реализации lock-free алгоритмов:
import "sync/atomic"
var counter int64
func increment() {
atomic.AddInt64(&counter, 1)
}
func load() int64 {
return atomic.LoadInt64(&counter)
}
Оптимизированная concurrent map с комбинацией lock-free и locked подходов:
var m sync.Map
m.Store("key", "value") // Lock-free для частых случаев
value, ok := m.Load("key")
Хотя каналы используют внутренние блокировки, они предоставляют lock-free-like интерфейс:
ch := make(chan int, 1)
ch <- 42 // Конкурентная отправка
val := <-ch // Конкурентное получение
type LockFreeQueue struct {
head unsafe.Pointer
tail unsafe.Pointer
}
func (q *LockFreeQueue) Enqueue(value interface{}) {
new := &node{value: value}
for {
tail := atomic.LoadPointer(&q.tail)
if atomic.CompareAndSwapPointer(&q.tail, tail, unsafe.Pointer(new)) {
// Успешная вставка
break
}
}
}
Go предоставляет базовые примитивы для реализации lock-free структур через sync/atomic
и оптимизированные concurrent структуры вроде sync.Map
. Полностью lock-free алгоритмы требуют ручной реализации с использованием атомарных операций и тщательного тестирования на гонки данных.