πŸ’¬ Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ атомарная опСрация ΠΈ для Ρ‡Π΅Π³ΠΎ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ ΠΏΠ°ΠΊΠ΅Ρ‚ atomic?



Атомарная опСрация выполняСтся Π·Π° ΠΎΠ΄ΠΈΠ½ шаг ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΈΠ»ΠΈ, Π² контСкстС Go, Π΄Ρ€ΡƒΠ³ΠΈΡ… Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ нСльзя ΠΏΡ€Π΅Ρ€Π²Π°Ρ‚ΡŒ Π² сСрСдинС Π΅Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹.



Бтандартная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Go содСрТит ΠΏΠ°ΠΊΠ΅Ρ‚ atomic, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΈΜ† Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… простых случаях ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΌΠΎΡ‡ΡŒ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ использования ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠ°. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½Π΅Π³ΠΎ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ доступ ΠΊ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹ΠΌ счСтчикам ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½, Π½Π΅ имСя ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с синхронизациСй ΠΈ Π½Π΅ бСспокоясь ΠΎ race condition.



Как ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π½ΠΈΠΆΠ΅, ΠΏΡ€ΠΈ использовании Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΈΜ† ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΈΜ† Π²ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ race condition всС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ чтСния ΠΈ записи Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΈΜ† ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΈΜ† Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈΜ†, прСдоставляСмых ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠΌ atomic.



package main

import (

"fmt"

"sync"

"sync/atomic"

)



type atomCounter struct {

val int64 }





Π­Ρ‚ΠΎ структура для хранСния Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΠΎΠΈΜ† Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΈΜ† ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΈΜ† int64.



func (c *atomCounter) Value() int64 {

return atomic.LoadInt64(&c.val)

}





Π­Ρ‚ΠΎ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Π°Ρ функция, которая Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΈΜ† ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΈΜ† int64, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ atomic.LoadInt64().



func main() {

X := 100

Y := 4

var waitGroup sync.WaitGroup

counter := atomCounter{}

for i := 0; i < X; i++ {





ΠœΡ‹ создаСм мноТСство Π³ΠΎΡ€ΡƒΡ‚ΠΈΠ½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ·ΠΌΠ΅Π½ΡΡŽΡ‚ ΠΎΠ±Ρ‰ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ. Благодаря использованию ΠΏΠ°ΠΊΠ΅Ρ‚Π° atomic для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΎΠ±Ρ‰Π΅ΠΈΜ† ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΈΜ† ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ простой способ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ race condition ΠΏΡ€ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Π΅Π΅ значСния.



        waitGroup.Add(1)

go func(no int) {

defer waitGroup.Done()

for i := 0; i < Y; i++ {

atomic.AddInt64(&counter.val, 1)

}





Ѐункция atomic.AddInt64() бСзопасно измСняСт Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ поля val структуры counter.



            }(i) 

}



waitGroup.Wait()

fmt.Println(counter.Value())

}