Sobes.tech
Middle+

Ako je bezpečné prenášať slices do rôznych goroutines?

sobes.tech AI

Odpoveď od AI

Prenos sľazu priamo do rôznych gorutín nie je bezpečný, ak ich gorutiny budú meniť súčasne bez synchronizácie alebo ak sa sľaz mení v jednej gorutine po jeho prenose (podľa kópie hlavičky) do inej.

Dôvody nebezpečenstva:

  • Zdieľaný základný poľ: Sľazy sú hlavičky (ukazovateľ na základný poľ, dĺžka, kapacita), ktoré ukazujú na spoločný základný poľ.
  • Stav závodu (Race Condition): súčasný zápis do rovnakého prvku základného poľa alebo zmena jeho veľkosti z rôznych gorutín povedie k stavu závodu, nepredvídateľným výsledkom a chybám.

Bezpečné spôsoby práce so sľazmi v gorutínach:

  1. Prenos kópie sľazu: Vytvoriť úplnú kópiu sľazu a preniesť ju. To je bezpečné, pretože gorutiny pracujú s oddelenými dátami.

    // vytvorenie úplnej kópie sľazu
    newSlice := make([]int, len(originalSlice))
    copy(newSlice, originalSlice)
    
  2. Použitie kanálov: Prenášať prvky sľazu alebo samotný sľaz cez kanály. Kanály zabezpečujú synchronizáciu a izoláciu dát.

    // prenášanie prvkov cez kanál
    ch := make(chan int)
    go func() {
        for _, v := range originalSlice {
            ch <- v
        }
        close(ch)
    }()
    
    // prenášanie sľazu cez kanál
    chSlice := make(chan []int)
    go func() {
        chSlice <- originalSlice // prenášanie podľa hlavičky, ale kanál synchronizuje
                                // dôležité: nemeniť originalSlice po odoslaní
    }()
    
  3. Synchronizácia pomocou sync.Mutex alebo sync.RWMutex: Chrániť prístup ku sľazu pomocou mutexov. To zabezpečuje, že iba jedna gorutina môže meniť sľaz v akomkoľvek momente.

    import "sync"
    
    var mu sync.Mutex
    var sharedSlice []int
    
    func modifySlice(index, value int) {
        mu.Lock()
        defer mu.Unlock()
        if index < len(sharedSlice) {
            sharedSlice[index] = value
        }
    }
    

Porovnanie prístupov:

Prístup Bezpečnosť Výkon pri veľkých sľazoch Zložitosť
Kópia sľazu Vysoká Nižšia (kopírovanie dát) Jednoduchá
Kanály Vysoká Závisí (náklady operácií kanála) Stredná
Mutexy Vysoká Vysoká (ak nie sú silné konflikty) Stredná

Preto, prenos hlavičky sľazu ako predvolený do rôznych gorutín bez ďalšej synchronizácie alebo kopírovania nie je bezpečný. Je potrebné použiť niektorú z vyššie uvedených metód na zabezpečenie bezpečnosti dát.