Sobes.tech
Middle

რა უნდა იფიქრო, როდესაც მუშაობთ mutex-ებთან Go-ში?

sobes.tech AI

პასუხი AI-სგან

Go-да sync.Mutex менен иштөөдө төмөнкүлөрдү эске алуу маанилүү:

  • Загвар жана бошотуу: Мьютекс зарыл болгон учурда (Lock()) бөлүшүлгөн маалыматтарга кирүү алдында жана иш аяктагандан кийин (Unlock()) бошотулушу керек. defer mu.Unlock() колдонуу mu.Lock() кийинки учурда жакшы практика болуп саналат, ал унутулуп калуудан сактайт.
  • Синхрондоштуруу уруксаты: Мьютекс бир мезгилде бир гана горутинге ресурска эксклюзивдүү кирүүгө мүмкүндүк берет.
  • "Блоктолгон/блоктонбогон" абал: Эгер Lock() кайра чакырылса, ал учурдагы блоктолгон мьютекс кайра чакырган горутинди токтотуп турат, башкача айтканда, башка горутиндер мьютекс бошотулмайынча күтүшөт. Unlock() чакырылса, ал бошотулган мьютекс менен паникага алып келет.
  • Мьютекстерди көчүрбөңүз: sync.Mutex структурасы биринчи колдонулгандан кийин көчүрүлүүгө арналган эмес. Мьютексти маанилер аркылуу берүү же структураны көчүрүү туура эмес синхрондоштуруу жана паникага алып келиши мүмкүн.
  • Deadlock (өткөрүү): Эки же андан көп горутин бири-биринен ресурстарды бошотушун күтүп турганда пайда болот. Типтүү сценарий: A горутини R1 ресурсын бөгөп, R2 күтүп жатат, ал эми B горутини R2 бөгөп, R1 күтүп жатат.
  • Livelock (жандуу блок): Горутинилер үзгүлтүксүз өз абалдарын өзгөртүп турушат, башкараак иш жасабай туруп, бирок алга жылышпайт. Бул deadlockко караганда сейрек кездешет.
  • Голодание: Бир же бир нече горутиндер бөлүшүлгөн ресурска жетүү мүмкүнчүлүгүн жоготушат, анткени башка горутиндер аны үзгүлтүксүз колдонуп жатышат. Go мьютекстеринде голодание кепилденбейт.
  • sync.RWMutex колдонуу окуу/жазуу үчүн: Эгер көбүнчө окуу операциялары болсо жана жазуу сейрек болсо, sync.RWMutex натыйжалуу болушу мүмкүн. Ал бир нече горутиндерге бир убакта окууга мүмкүндүк берет, бирок жазуу учурунда бардык окуу жана башка жазууларды блоктойт.
  • Кыска блоктоолор: Блоктоолорду мүмкүн болушунча кыска кармаңыз. Мьютекс узак убакыт бою жабык болсо, башка горутиндер күтүшү мүмкүн, бул параллелизмди төмөндөтөт.
  • Тесттерди жарышта текшерүү: -race флагын колдонуу go test тесттерин түзүү жана иштетүүдө жарыштарды аныктоого жардам берет, ал көбүнчө туура эмес мьютекс колдонуу менен байланыштуу.

defer колдонуу мисалы:

import (
	"sync"
)

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

// Inc бул белгилүү ачкыч үчүн санагычты коопсуз түрдө көбөйтөт.
func (c *SafeCounter) Inc(key string) {
	c.mu.Lock()
	// Босотуу функциянын аягында жасалат деп күтүлөт.
	defer c.mu.Unlock()
	c.v[key]++
}

// Value бул белгилүү ачкыч үчүн учурдагы санагыч маанисин кайтарат.
func (c *SafeCounter) Value(key string) int {
	c.mu.Lock()
	// Маалыматты алуу аяктагандан кийин бошотуу күтүлөт.
	defer c.mu.Unlock()
	return c.v[key]
}