Mutexes

Mutexes #

// ပြီးခဲ့တဲ့ဥပမာမှာ [atomic operation](atomic-counters) တွေသုံးပြီး ရိုးရှင်းတဲ့
// counter state ကို ဘယ်လိုစီမံခန့်ခွဲသလဲဆိုတာ တွေ့ခဲ့ပါတယ်။
// ပိုရှုပ်ထွေးတဲ့ state တွေအတွက်တော့ goroutine အများကြီးကြားထဲမှာ ဒေတာကို
// လုံခြုံစွာ access လုပ်ဖို့ [_mutex_](https://en.wikipedia.org/wiki/Mutual_exclusion) ကို သုံးနိုင်ပါတယ်။

package main

import (
	"fmt"
	"sync"
)

// Container က counter တွေရဲ့ map ကို သိမ်းထားပါတယ်။ ဒီ map ကို
// goroutine အများကြီးကနေ တပြိုင်နက်တည်း update လုပ်ချင်တဲ့အတွက်
// access ကို synchronize လုပ်ဖို့ `Mutex` တစ်ခု ထည့်ထားပါတယ်။
// သတိပြုရမှာက mutex တွေကို copy မလုပ်သင့်ပါဘူး၊ ဒါကြောင့် ဒီ `struct` ကို
// တခြားနေရာတွေဆီ ပို့မယ်ဆိုရင် pointer နဲ့ပို့သင့်ပါတယ်။
type Container struct {
	mu       sync.Mutex
	counters map[string]int
}

func (c *Container) inc(name string) {
	// `counters` ကို access မလုပ်ခင် mutex ကို lock လုပ်ပါ။
	// function အဆုံးမှာ unlock လုပ်ဖို့ [defer](defer) statement ကို သုံးထားပါတယ်။
	c.mu.Lock()
	defer c.mu.Unlock()
	c.counters[name]++
}

func main() {
	c := Container{
		// Mutex ရဲ့ zero value က အသုံးပြုလို့ရပါတယ်၊ ဒါကြောင့် ဒီမှာ
		// သီးခြား initialization လုပ်စရာမလိုပါဘူး။
		counters: map[string]int{"a": 0, "b": 0},
	}

	var wg sync.WaitGroup

	// ဒီ function က နာမည်ပေးထားတဲ့ counter ကို loop ထဲမှာ တိုးပေးပါတယ်။
	doIncrement := func(name string, n int) {
		for i := 0; i < n; i++ {
			c.inc(name)
		}
		wg.Done()
	}

	// Goroutine အများကြီးကို တပြိုင်နက်တည်း run တာပါ။
	// သတိပြုရမှာက သူတို့အားလုံးက တူညီတဲ့ `Container` ကိုပဲ access လုပ်နေပြီး
	// နှစ်ခုကတော့ တူညီတဲ့ counter ကိုပဲ access လုပ်နေပါတယ်။
	wg.Add(3)
	go doIncrement("a", 10000)
	go doIncrement("a", 10000)
	go doIncrement("b", 10000)

	// Goroutine တွေ ပြီးဆုံးတဲ့အထိ စောင့်ပါ
	wg.Wait()
	fmt.Println(c.counters)
}
# ပရိုဂရမ်ကို run လိုက်တဲ့အခါ counter တွေက
# ကျွန်တော်တို့ မျှော်လင့်ထားသလိုပဲ update 
# ဖြစ်သွားတာကို တွေ့ရပါတယ်။
$ go run mutexes.go
map[a:20000 b:10000]

# နောက်တစ်ဆင့်မှာ ဒီလို state စီမံခန့်ခွဲမှုကိုပဲ
# goroutine တွေနဲ့ channel တွေကိုပဲ 
# သုံးပြီး အကောင်အထည်ဖော်တာကို ကြည့်ကြပါမယ်။