Sobes.tech
Middle

Go'da mutexlar bilan ishlashda nima yodda tutish kerak?

sobes.tech AI

AIdan javob

Go tilida (sync.Mutex) mutexlar bilan ishlashda quyidagilarni esda tutish muhim:

  • Yopish va ochish: Mutexni majburiy ravishda (Lock()) umumiy ma'lumotlarga kirishdan oldin yopish va (Unlock()) u bilan ishlash tugagach ochish. defer mu.Unlock() ni mu.Lock() dan darhol keyin ishlatish yaxshi amaliyot bo'lib, uni unutishni oldini oladi.
  • Ekskluziv kirish: Mutex faqat bitta goroutinega resursga ekskluziv kirishni ta'minlaydi.
  • "Bloklangan/ochilgan" holat: Agar Lock() chaqirilsa, va mutex allaqachon bloklangan bo'lsa, chaqiruvchi goroutine bloklanadi, boshqa goroutine uni ochmaguncha. Unlock() ochilmagan mutexda chaqirilsa, runtime panic yuzaga keladi.
  • Mutexlarni nusxalash mumkin emas: sync.Mutex strukturasini birinchi foydalanishdan keyin nusxalash uchun mo'ljallamagan. Uni qiymat sifatida uzatish yoki mutexni o'z ichiga olgan struktura nusxalash noto'g'ri sinxronizatsiyaga va panikaga olib kelishi mumkin.
  • Deadlock (qaytib yopish): Bu, ikki yoki undan ortiq goroutine'lar bir-birining resurslarini bo'shatishini kutayotgan holat. Tipik holat: A goroutine R1ni bloklaydi va R2ni kutadi, B goroutine R2ni bloklaydi va R1ni kutadi.
  • Livelock (jonli yopish): Goroutine'lar doim holatlarini o'zgartirib, bir-birining harakatlariga javob berishadi, lekin foydali ish qilmaydi va oldinga siljimasdan qoladi. Bu deadlockdan kamroq uchraydi.
  • Ochlik (starvation): Bir yoki bir nechta goroutine'lar umumiy resursga kirish imkoniga ega emas, chunki uni doim boshqa goroutine'lar bloklaydi. Go mutexlarida ochlik kafolatlanmagan.
  • sync.RWMutex dan o'qish/yozish uchun foydalanish: Agar ko'p operatsiyalar o'qish bo'lsa va yozish kam bo'lsa, sync.RWMutex samaraliroq bo'lishi mumkin. U bir vaqtning o'zida ko'p goroutine'lar o'qishga ruxsat beradi, lekin yozish paytida hamma o'qish va yozishni bloklaydi.
  • Qisqa bloklar: Bloklarni imkon qadar qisqa tutishga harakat qiling. Mutex uzoq vaqt bloklangan bo'lsa, boshqa goroutine'lar kutadi, bu parallelizmni kamaytiradi.
  • Yarish shartlarini test qilish: -race bayrog'idan foydalanish, testlarni yig'ish va ishga tushirishda (go test -race) yarish shartlarini aniqlashga yordam beradi, ular ko'pincha mutexlarni noto'g'ri ishlatish natijasida yuzaga keladi.

defer dan foydalanish misoli:

import (
	"sync"
)

type SafeCounter struct {
	mu sync.Mutex
	v  map[string]int
}

// Inc, kalit uchun hisoblagichni xavfsiz tarzda oshiradi.
func (c *SafeCounter) Inc(key string) {
	c.mu.Lock()
	// Funktsiyadan chiqishda ochamiz.
	defer c.mu.Unlock()
	c.v[key]++
}

// Value, kalit uchun hozirgi hisoblagich qiymatini qaytaradi.
func (c *SafeCounter) Value(key string) int {
	c.mu.Lock()
	// Qiymatni olgach, ochamiz.
	defer c.mu.Unlock()
	return c.v[key]
}