Sobes.tech
Middle+

Kiek saugu naudoti slices konkurencijos (Concurrency) kontekste?

sobes.tech AI

Atsakymas iš AI

Naudojant sraigtus yra nesaugus konkurencijos kontekste be papildomų sinchronizacijos mechanizmų. Daugybinis vienu metu vykstantis skaitymas ir rašymas arba du vienu metu vykstantys rašymai į tą pačią atminties dalį (kuri yra pagrindinis sraigtas masyvas) sukelia duomenų lenktynių būseną (data race).

nesaugumo priežastys:

  1. Pagrindinio masyvo keitimas: Sraigtas yra pagrindinio masyvo vaizdas. Elementų pridėjimo operacijos (append), ypač jei jos viršija dabartinį talpą, gali sukelti naujo atminties paskirstymo ir duomenų kopijavimo į naują masyvą. Jei tuo metu kita gorutina bando skaityti ar rašyti seną ar naują masyvą, įvyksta duomenų lenktynės.
  2. Sraigto antraštės keitimas: Pats sraigto antraštė (struct, kuriame yra nuoroda į pagrindinį masyvą, ilgis ir talpa) taip pat gali būti keičiama append operacijos metu. Vienu metu skaityti ir rašyti šią antraštę be blokavimo sukelia nenuspėjamą elgesį.

saugumo užtikrinimo mechanizmai:

  • sync.Mutex / sync.RWMutex: Prieigos blokavimas prie sraigto prieš kiekvieną skaitymo ar rašymo operaciją. sync.RWMutex yra tinkamesnis dažnam skaitymui ir retkam rašymui.

    import "sync"
    
    type SafeSlice struct {
        mu    sync.RWMutex
        items []int
    }
    
    func (s *SafeSlice) Append(item int) {
        s.mu.Lock() // Užrakinti rašymui
        defer s.mu.Unlock()
        s.items = append(s.items, item)
    }
    
    func (s *SafeSlice) Get(index int) (int, bool) {
        s.mu.RLock() // Užrakinti skaitymui
        defer s.mu.RUnlock()
        if index < 0 || index >= len(s.items) {
            return 0, false
        }
        return s.items[index], true
    }
    
  • Kanalai (Channels): Duomenų perdavimas per kanalus. Viena gorutina rašo duomenis, kita juos skaito iš kanalo. Tai tinka srautinio duomenų apdorojimo scenarijams.

    // Pavyzdys naudojant kanalą duomenims perduoti
    // scenarijuje, kur viena gorutina gamina, kita naudoja
    
  • sync.Map: Tinka, jei sraigtas naudojamas kaip raktų ir reikšmių žemėlapio pagrindas arba scenarijuose, kur tvarka nėra svarbi, bet konkurencinė saugumas — kritiškai svarbus.

Išvada: Naudojant sraigtus konkurenciniuose scenarijuose, reikia aiškiai valdyti sinchronizaciją, kad būtų išvengta duomenų lenktynių. Paprastas prieigos prie sraigto iš kelių gorutinių vienu metu nėra saugus.