В языке Go конкурентный доступ к одной ячейке памяти можно реализовать с помощью мьютексов или атомарных операций.
Мьютексы в Go представлены типом sync.Mutex
. Мьютекс позволяет заблокировать доступ к определенному участку кода только для одной горутины одновременно, что гарантирует корректность работы с общей ячейкой памяти. Для использования мьютекса, необходимо вызвать его метод Lock()
перед доступом к общей ячейке памяти и метод Unlock()
после завершения работы с ячейкой. Это обеспечит синхронизацию доступа к ячейке для всех горутин:
package main import ( "fmt" "sync" ) var sharedData int var mutex sync.Mutex func main() { var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() mutex.Lock() sharedData = 42 mutex.Unlock() }() go func() { defer wg.Done() mutex.Lock() fmt.Println(sharedData) mutex.Unlock() }() wg.Wait() }
Атомарные операции в Go используются для выполнения чтения и записи к ячейке памяти одновременно без блокировки. Go предоставляет набор атомарных операций в пакете sync/atomic
, таких как AddInt32
, LoadInt64
, StorePointer
, и т. д. При использовании атомарных операций, несколько горутин могут одновременно изменять или считывать значение общей ячейки памяти без необходимости блокировки:
package main import ( "fmt" "sync/atomic" ) var sharedData int32 func main() { var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() atomic.StoreInt32(&sharedData, 42) }() go func() { defer wg.Done() fmt.Println(atomic.LoadInt32(&sharedData)) }() wg.Wait() }
Обратите внимание, что при работе с конкурентным доступом к одной ячейке памяти, необходимо быть внимательными и проверять наличие гонок данных (data races). Гонка данных возникает, когда несколько горутин обращаются к общей ячейке памяти без синхронизации и приводит к неопределенным результатам. Поэтому использование мьютексов или атомарных операций необходимо в случае, когда одна ячейка памяти изменяется и считывается из разных горутин.