মূল কন্টেন্টে যান
মডিউল 7 · 4-এর পাঠ 5কোর্সে 34/50~14 min
মডিউল পাঠ (4/5)

`sync.Mutex` এবং `sync.WaitGroup`

চ্যানেলগুলি হল গো-এর প্রাথমিক বাগধারা, কিন্তু কখনও কখনও আরও ঐতিহ্যবাহী আদিম প্রয়োজন। sync প্যাকেজটি মিউটেক্স প্রদান করে, অপেক্ষা করুন গ্রুপ এবং অন্যান্য ইউটিলিটি শেয়ার্ড স্টেট সমন্বয় করতে।

sync.Mutex: একচেটিয়া লক

Go
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: অনেক পাঠক, একজন লেখক

পড়া-ভারী অবস্থার জন্য:

Go
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 এর জন্য অপেক্ষা করুন

Go
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

কর্মপ্রবাহ:

  1. wg.Add(N) কাউন্টারটিকে N দ্বারা বৃদ্ধি করে (গোরুটিন চালু করার আগে)।
  2. প্রতিটি গোরুটিন শেষ হলে wg.Done() এ কল করে (আদর্শভাবে defer এর মাধ্যমে)।
  3. wg.Wait() কাউন্টারটি 0-এ ফিরে না যাওয়া পর্যন্ত ব্লক করে।

sync.Once: থ্রেড-সেফ অলস ইনিশিয়ালাইজেশন

Go
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 এর সাথে পরীক্ষা চালান:

Bash
go test -race ./...
go run -race main.go

রেস ডিটেক্টর বাইনারি যন্ত্র এবং প্রতিটি আনসিঙ্ক্রোনাইজ লগ লগ ভাগ করা মেমরিতে অ্যাক্সেস। সমবর্তী কোড যাচাই করার জন্য এটি টুল #1 উৎপাদনের আগে।

চেষ্টা করে দেখুন

ব্যায়াম#go.m7.l4.e1
প্রচেষ্টা: 0লোড হচ্ছে...

mu.Lock() + defer mu.Unlock() দিয়ে গণনার বৃদ্ধি রক্ষা করুন।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

আতঙ্কের মধ্যেও Lock() মুক্তির গ্যারান্টি দেওয়ার ঠিক পরে mu.Unlock() স্থগিত করুন।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

ব্যায়াম#go.m7.l4.e2
প্রচেষ্টা: 0লোড হচ্ছে...

3টি গোরুটিন চালু করুন এবং সিঙ্ক ব্যবহার করে তাদের সকলের জন্য অপেক্ষা করুন। প্রতিটি গোরুটিনে ওয়েটগ্রুপ (অ্যাড(3), সম্পন্ন(), অপেক্ষা করুন())।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

গোরুটিন চালু করার আগে যোগ করুন; ডিফারের সাথে গোরুটিনের ভিতরে সম্পন্ন।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

Quiz#go.m7.l4.e3
প্রস্তুত

মিউটেক্স মুক্তির গ্যারান্টি দেওয়ার জন্য প্রস্তাবিত প্যাটার্ন কী?

Go
mu.Lock()
// ?
উত্তরের বিকল্প

রিক্যাপ

  • sync.Mutex ভাগ করা রাষ্ট্রকে রক্ষা করে; সর্বদা defer mu.Unlock()।
  • মিউটেক্স কপি এড়াতে একটি পয়েন্টার রিসিভার ব্যবহার করুন।
  • sync.RWMutex অনেক-পাঠক/এক-লেখকের নিদর্শনগুলির জন্য (শুধুমাত্র যদি এটি সাহায্য করে)।
  • sync.WaitGroup: Add এর আগে go, Done এর সাথে defer, Wait অপেক্ষা করুন৷
  • sync.Once: থ্রেড-নিরাপদ অলস প্রাথমিককরণ।
  • "অর্কেস্ট্রেট করার জন্য চ্যানেল, শেয়ার করা ডেটার জন্য মিউটেক্স"।
  • go test -race: টুল #1 ডেটা রেস চিহ্নিত করতে।