Šta je mutex, koje vrste mutexa postoje i kako ih koristiti?
sobes.tech АИ
Одговор од АИ
Мьютекс (од англ. MUTual EXclusion) — тој е примитив за синхронизација кој се користи за обезбедување исклучителен пристап до заеднички ресурс меѓу конкурирачките горутини. Гарантира дека во секој момент само една горутиња може да поседува мьютекс и соодветно да пристапува до заштитените податоци.
Во Go, пакетот sync обезбедува два главни типа на мьютекси:
-
sync.Mutex: Стандарден мьютекс. Обезбедува методиLock()иUnlock(). Ако мьютексот веќе е заклучен, повикотLock()ја блокира тековната горутиња додека не биде ослободен.Unlock()ја отклучува мьютексот.var mu sync.Mutex var counter int func increment() { mu.Lock() // Блокира пристап до counter counter++ mu.Unlock() // Отклучува пристап } -
sync.RWMutex: Мьютекс за читање/запишување. Ова дозволува повеќе горутини да читаат истовремено заштитениот ресурс, но само една да пишува. Обезбедува методиLock(),Unlock()(за запишување),RLock()иRUnlock()(за читање).var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Блокира за читање // Читање data fmt.Println(data) rwMu.RUnlock() // Отклучува читање } func writeData(val int) { rwMu.Lock() // Блокира за запишување // Запишување во data data = append(data, val) rwMu.Unlock() // Отклучува запишување }
Користењето на мьютекси е неопходно за спречување состојби на трка (race conditions), кога повеќе горутини истовремено се обидуваат да модифицираат исти податоци, што може да доведе до непредвидливи резултати.
Правила за користење:
- Повикај
Lock()пред пристапот до заштитениот ресурс. - Повикај
Unlock()по завршувањето на пристапот. Препорачливо е да се користиdefer mu.Unlock()за гарантирање на отклучувањето дури и во случај на паника. - Не се обидувај да заклучиш веќе заклучен мьютекс од истата горутиња (може да доведе до дедлок).
- Не се обидувај да отклучиш незаклучен мьютекс.
- Кога се користи
RWMutex, користиRLock/RUnlockза операции на читање иLock/Unlockза операции на запишување. - Мьютексите не треба да се копираат по првото користење. Тие треба да се пренесуваат по референца или покажувач.
Пример за користење defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Гарантира отклучување
counter++
}