Sobes.tech
Middle

Може ли исти []byte бафер да се користи у више горутина?

sobes.tech АИ

Одговор од АИ

Da, može, ali je potrebno obezbediti sinhronizaciju pristupa kako bi se sprečile trke podataka.

Najčešći pristupi:

  1. Muteksi (sync.Mutex):

    import "sync"
    
    var buf []byte
    var mu sync.Mutex
    
    func processBuffer() {
        mu.Lock()
        defer mu.Unlock()
        // Siguran pristup buf
        // Na primer: buf = append(buf, data...)
    }
    
    func main() {
        // Inicijalizacija buf
        go processBuffer()
        go processBuffer()
        // ...
    }
    
  2. Kanal (chan):

    Možete prenositi vlasništvo nad baferom između gorutina ili koristiti kanal za koordinaciju pristupa.

    import "bytes"
    
    type BufferAccess struct {
        buf *bytes.Buffer // Pokazivač na bafer za zajedničko korišćenje
        mu  sync.Mutex    // Muteks za sinhronizaciju pristupa
    }
    
    func (ba *BufferAccess) Write(p []byte) (n int, err error) {
        ba.mu.Lock()
        defer ba.mu.Unlock()
        return ba.buf.Write(p)
    }
    
    func worker(ba *BufferAccess, data []byte) {
        ba.Write(data) // Siguran zapis putem metode sa muteksom
    }
    
    func main() {
        sharedBuffer := &BufferAccess{buf: &bytes.Buffer{}}
        // Pokretanje gorutina, prosleđujući sharedBuffer
        go worker(sharedBuffer, []byte("hello"))
        go worker(sharedBuffer, []byte("world"))
        // ...
    }
    
  3. Pool bafera (sync.Pool):

    Manje je potrebno sinhronizovati pristup samom baferu, ako svaka gorutina uzima bafer iz poola, koristi ga, a zatim vraća.

    import (
        "bytes"
        "sync"
    )
    
    var bufferPool = sync.Pool{
        New: func() interface{} {
            // Podrazumevana veličina bafera
            return bytes.NewBuffer(make([]byte, 0, 1024))
        },
    }
    
    func processData(data []byte) {
        buf := bufferPool.Get().(*bytes.Buffer)
        defer bufferPool.Put(buf) // Obavezno vratiti bafer u pool
    
        buf.Reset() // Očistiti bafer pre korišćenja
        buf.Write(data)
        // Obrada podataka u baferu
        // ...
    }
    
    func main() {
        go processData([]byte("message1"))
        go processData([]byte("message2"))
        // ...
    }
    

Važno: Korišćenje bafera bez sinhronizacije u konkurentnom okruženju dovodi do stanja trke podataka, što je uzrok nepredvidivom ponašanju programa i teže uočljivim greškama.