Sobes.tech
Middle+

Jak je bezpečné používat slices v kontextu konkurenčního provádění (Concurrency)?

sobes.tech AI

Odpověď od AI

Použití slice není bezpečné v kontextu konkurenčního přístupu (Concurrency) bez dalších mechanismů synchronizace. Vícenásobný současný přístup ke čtení a zápisu nebo dva současné zápisy do stejné oblasti paměti (kterou je základní pole slice) vede ke stavu závodu (data race).

Důvody nebezpečí:

  1. Změna základního pole: Slice je zobrazením základního pole. Operace přidání prvků (append), zejména pokud překročí aktuální kapacitu, může vést k re-alokaci a kopírování dat do nového základního pole. Pokud v té době jiná gorutina pokouší se číst nebo zapisovat do starého nebo nového základního pole, vzniká race condition.
  2. Změna hlavičky slice: Samotná hlavička slice (struktura obsahující ukazatel na základní pole, délku a kapacitu) může být změněna při operacích jako append. Současné čtení a zápis této hlavičky bez zámků vede k neurčitelnému chování.

Mechanismy pro zajištění bezpečnosti:

  • sync.Mutex / sync.RWMutex: Zámek přístupu ke slice před každou operací čtení nebo zápisu. sync.RWMutex je preferován pro scénáře s častým čtením a vzácným zápisem.

    import "sync"
    
    type SafeSlice struct {
        mu    sync.RWMutex
        items []int
    }
    
    func (s *SafeSlice) Append(item int) {
        s.mu.Lock() // Zamyká pro zápis
        defer s.mu.Unlock()
        s.items = append(s.items, item)
    }
    
    func (s *SafeSlice) Get(index int) (int, bool) {
        s.mu.RLock() // Zamyká pro čtení
        defer s.mu.RUnlock()
        if index < 0 || index >= len(s.items) {
            return 0, false
        }
        return s.items[index], true
    }
    
  • Kanály (Channels): Přenos vlastnictví dat přes kanály. Jedna gorutina zapisuje data, jiná je čte z kanálu. To je vhodné pro scénáře streamového zpracování dat.

    // Příklad použití kanálu pro přenos prvků
    // v scénáři, kde jedna gorutina produkuje, druhá spotřebovává
    
  • sync.Map: Vhodné, pokud je slice používán jako základ pro mapování klíčů na hodnoty nebo v scénářích, kde pořadí není důležité, ale kritická je konkurenční bezpečnost.

Závěr: Použití slice v konkurenčních scénářích vyžaduje explicitní správu synchronizace, aby se zabránilo závodům dat. Jednoduchý přístup k slice z více gorutin současně není bezpečný.