Sobes.tech
Middle+

Koliko je sigurno koristiti slices u kontekstu konkurentnog izvršavanja (Concurrency)?

sobes.tech АИ

Одговор од АИ

Korišćenje sliceova nije sigurno u kontekstu konkurentnog pristupa (Concurrency) bez dodatnih mehanizama za sinhronizaciju. Višestruki istovremeni pristupi za čitanje i pisanje ili dva istovremena pristupa za pisanje na istu memorijsku lokaciju (koja je osnovni niz sličice) dovode do stanja trke podataka (data race).

Razlozi za unsafe:

  1. Promena osnovnog niza: Sličica je prikaz osnovnog niza. Operacije dodavanja elemenata (append), posebno ako pređu trenutni kapacitet, mogu dovesti do re- alokacije i kopiranja podataka u novi osnovni niz. Ako u tom trenutku druga gorutina pokušava da čita ili piše u stari ili novi osnovni niz, javlja se race condition.
  2. Promena zaglavlja sličice: Samo zaglavlje sličice (struct, koji sadrži pokazivač na osnovni niz, dužinu i kapacitet) takođe može biti izmenjeno tokom operacija poput append. Istovremeno čitanje i pisanje tog zaglavlja bez blokada dovodi do neodređenog ponašanja.

Mehanizmi za obezbeđivanje sigurnosti:

  • sync.Mutex / sync.RWMutex: Zaključavanje pristupa sličici pre svake operacije čitanja ili pisanja. sync.RWMutex je poželjniji za scenarije sa čestim čitanjem i retkim pisanjem.

    import "sync"
    
    type SafeSlice struct {
        mu    sync.RWMutex
        items []int
    }
    
    func (s *SafeSlice) Append(item int) {
        s.mu.Lock() // Zaključavamo za pisanje
        defer s.mu.Unlock()
        s.items = append(s.items, item)
    }
    
    func (s *SafeSlice) Get(index int) (int, bool) {
        s.mu.RLock() // Zaključavamo za čitanje
        defer s.mu.RUnlock()
        if index < 0 || index >= len(s.items) {
            return 0, false
        }
        return s.items[index], true
    }
    
  • Kanal (Channels): Prenos vlasništva nad podacima putem kanala. Jedna gorutina zapisuje podatke, druga ih čita iz kanala. Ovo je pogodno za scenarije stream obrade podataka.

    // Primer korišćenja kanala za prenos elemenata
    // u scenariju gde jedna gorutina proizvodi, a druga konzumira
    
  • sync.Map: Pogodno ako se sličica koristi kao osnova za mapiranje ključeva na vrednosti ili u scenarijima gde redosled nije važan, ali je kritična konkurentna sigurnost.

Zaključak: Korišćenje sličica u konkurentnim scenarijima zahteva jasno upravljanje sinhronizacijom radi sprečavanja trka podataka. Jednostavan pristup sličici iz više gorutina istovremeno nije siguran.