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.