মডিউল পাঠ (4/5)
`sync.Mutex` এবং `sync.WaitGroup`
চ্যানেলগুলি হল গো-এর প্রাথমিক বাগধারা, কিন্তু কখনও কখনও আরও ঐতিহ্যবাহী
আদিম প্রয়োজন। sync প্যাকেজটি মিউটেক্স প্রদান করে, অপেক্ষা করুন
গ্রুপ এবং অন্যান্য ইউটিলিটি শেয়ার্ড স্টেট সমন্বয় করতে।
sync.Mutex: একচেটিয়া লক
import "sync"
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
func (c *Counter) Get() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}একবারে শুধুমাত্র এক গোরুটিন Lock() এবং Unlock() এর মধ্যে প্রবেশ করে।
বাধ্যতামূলক প্যাটার্ন: defer mu.Unlock() ঠিক Lock() এর পরে।
sync.RWMutex: অনেক পাঠক, একজন লেখক
পড়া-ভারী অবস্থার জন্য:
var mu sync.RWMutex
mu.RLock() // read lock: più goroutine simultanee OK
v := data
mu.RUnlock()
mu.Lock() // write lock: esclusivo
data = newValue
mu.Unlock()শুধুমাত্র লেখার উপর রিডিং প্রাধান্য দিলেই উপযোগী; অন্যথায় নিয়মিত
sync.Mutex কম অভ্যন্তরীণ ধন্যবাদ সহজ এবং প্রায়ই দ্রুত
বিবাদ
sync.WaitGroup: N goroutines এর জন্য অপেক্ষা করুন
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
work(id)
}(i)
}
wg.Wait() // blocca finché tutti i Done() sono arrivatiকর্মপ্রবাহ:
wg.Add(N)কাউন্টারটিকে N দ্বারা বৃদ্ধি করে (গোরুটিন চালু করার আগে)।- প্রতিটি গোরুটিন শেষ হলে
wg.Done()এ কল করে (আদর্শভাবেdeferএর মাধ্যমে)। wg.Wait()কাউন্টারটি 0-এ ফিরে না যাওয়া পর্যন্ত ব্লক করে।
sync.Once: থ্রেড-সেফ অলস ইনিশিয়ালাইজেশন
var (
once sync.Once
config *Config
)
func GetConfig() *Config {
once.Do(func() {
config = loadConfig()
})
return config
}once.Do এ কলব্যাক একবারই চলে, এমনকি সমসাময়িকেও
কল সিঙ্গলটন / অলস প্রারম্ভিক প্যাটার্ন।
মুটেক্স বনাম চ্যানেল: কখন কী ব্যবহার করবেন
নির্দেশিকা (আধিকারিক Go FAQ থেকেও):
| মামলা | পছন্দের টুল |
|---|---|
| ডেটার মালিকানা পাস করা | চ্যানেল |
| কাজ বিতরণ (কাজের সারি) | চ্যানেল |
| স্বাধীন গোরুটিন সমন্বয় | চ্যানেল |
| একটি struct ক্ষেত্র রক্ষা করা | Mutex |
| ক্যাশে / কাউন্টার | Mutex বা পারমাণবিক |
| সিঙ্গেলটন রেফারেন্স | sync.Once |
"অর্কেস্ট্রেট করার জন্য চ্যানেল, শেয়ার করা ডেটার জন্য মিউটেক্স" হল একটি ভাল নিয়ম।
রেস ডিটেক্টর
ডেটা রেস চিহ্নিত করতে -race এর সাথে পরীক্ষা চালান:
go test -race ./...
go run -race main.goরেস ডিটেক্টর বাইনারি যন্ত্র এবং প্রতিটি আনসিঙ্ক্রোনাইজ লগ লগ ভাগ করা মেমরিতে অ্যাক্সেস। সমবর্তী কোড যাচাই করার জন্য এটি টুল #1 উৎপাদনের আগে।
চেষ্টা করে দেখুন
mu.Lock() + defer mu.Unlock() দিয়ে গণনার বৃদ্ধি রক্ষা করুন।
ইঙ্গিত দেখান
আতঙ্কের মধ্যেও Lock() মুক্তির গ্যারান্টি দেওয়ার ঠিক পরে mu.Unlock() স্থগিত করুন।
সমাধান 3 প্রচেষ্টার পরে উপলব্ধ
3টি গোরুটিন চালু করুন এবং সিঙ্ক ব্যবহার করে তাদের সকলের জন্য অপেক্ষা করুন। প্রতিটি গোরুটিনে ওয়েটগ্রুপ (অ্যাড(3), সম্পন্ন(), অপেক্ষা করুন())।
ইঙ্গিত দেখান
গোরুটিন চালু করার আগে যোগ করুন; ডিফারের সাথে গোরুটিনের ভিতরে সম্পন্ন।
সমাধান 3 প্রচেষ্টার পরে উপলব্ধ
মিউটেক্স মুক্তির গ্যারান্টি দেওয়ার জন্য প্রস্তাবিত প্যাটার্ন কী?
mu.Lock()
// ?রিক্যাপ
sync.Mutexভাগ করা রাষ্ট্রকে রক্ষা করে; সর্বদাdefer mu.Unlock()।- মিউটেক্স কপি এড়াতে একটি পয়েন্টার রিসিভার ব্যবহার করুন।
sync.RWMutexঅনেক-পাঠক/এক-লেখকের নিদর্শনগুলির জন্য (শুধুমাত্র যদি এটি সাহায্য করে)।sync.WaitGroup:Addএর আগেgo,Doneএর সাথেdefer,Waitঅপেক্ষা করুন৷sync.Once: থ্রেড-নিরাপদ অলস প্রাথমিককরণ।- "অর্কেস্ট্রেট করার জন্য চ্যানেল, শেয়ার করা ডেটার জন্য মিউটেক্স"।
go test -race: টুল #1 ডেটা রেস চিহ্নিত করতে।