Atomic
Şimdide atomic isimli pakete bir bakalım.
Kendisi sync isimli paketin altında yer alıyor. Go’da paket altında paket
olabiliyor. [1]
Package atomic provides low-level atomic memory primitives useful for implementing synchronization algorithms.
Önemli
These functions require great care to be used correctly. Except for special, low-level applications, synchronization is better done with channels or the facilities of the sync package. Share memory by communicating; don’t communicate by sharing memory.
Aşağıdaki koda bakalım:
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
func main() {
fmt.Println("CPU sayısı:", runtime.NumCPU())
//runtime.GOMAXPROCS(1)
//runtime.GOMAXPROCS(0), değiştirmeden olanı dönüyor
fmt.Println("Maks. aktif thread sayısı (GOMAXPROC):", runtime.GOMAXPROCS(0))
var counter int32
const gs = 10000
var wg sync.WaitGroup
//vgs adedi kadar bekle
wg.Add(gs)
for i := 0; i < gs; i++ {
go func() {
atomic.AddInt32(&counter, 1)
runtime.Gosched()
fmt.Println("Counter=", atomic.LoadInt32(&counter))
wg.Done()
}()
fmt.Println("Goroutine sayısı:", runtime.NumGoroutine())
}
wg.Wait()
fmt.Println("counter:", counter, "beklenen:", gs)
}
Burada hiçbir Mutex benzeri koruma mekanizması yok. Ama arttırma işleminin
atomic olması için bunu atomic.AddInt32(&counter, 1) ile yapıyoruz. Aynı
şekilde goroutine içerisinden okurken de atomic.LoadInt32(&counter) ile
okuyoruz. Ama wg.Wait() sonrasında artık erişecek goroutine kalmadığını
bildiğimiz için counter ile doğrudan okuyoruz.