Middle
Ar galima naudoti tą patį []byte buferį keliuose goroutine'uose?
sobes.tech AI
Atsakymas iš AI
Taip, galima, tačiau būtina užtikrinti prieigos sinchronizaciją, kad būtų išvengta duomenų lenktynių.
Dažniausiai naudojami būdai:
-
MUTEX'ai (
sync.Mutex):import "sync" var buf []byte var mu sync.Mutex func processBuffer() { mu.Lock() defer mu.Unlock() // Saugi prieiga prie buf // Pavyzdžiui: buf = append(buf, data...) } func main() { // Buf inicijavimas go processBuffer() go processBuffer() // ... } -
Kanalai (
chan):Galite perduoti nuosavybę įrašui tarp gorutinių arba naudoti kanalą prieigos koordinavimui.
import "bytes" type BufferAccess struct { buf *bytes.Buffer // Bendra naudojama buferis mu sync.Mutex // Muteksas prieigos sinchronizacijai } 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) // Saugi įrašymas su muteksu } func main() { sharedBuffer := &BufferAccess{buf: &bytes.Buffer{}} // Gorutinių paleidimas, perduodant sharedBuffer go worker(sharedBuffer, []byte("hello")) go worker(sharedBuffer, []byte("world")) // ... } -
Buferių baseinas (
sync.Pool):Mažiau reikalinga sinchronizacija prieigos prie paties buferio, jei kiekviena gorutina paima buferį iš baseino, naudoja jį ir grąžina atgal.
import ( "bytes" "sync" ) var bufferPool = sync.Pool{ New: func() interface{} { // Numatytoji buferio dydis return bytes.NewBuffer(make([]byte, 0, 1024)) }, } func processData(data []byte) { buf := bufferPool.Get().(*bytes.Buffer) defer bufferPool.Put(buf) // Būtina grąžinti buferį į baseiną buf.Reset() // Išvalyti buferį prieš naudojimą buf.Write(data) // Duomenų apdorojimas // ... } func main() { go processData([]byte("message1")) go processData([]byte("message2")) // ... }
Svarbu: Naudojant buferį be sinchronizacijos konkurentiniame aplinkoje, gali įvykti duomenų lenktynės, kurios sukelia nenuspėjamą elgesį ir sunkiai diagnozuojamas klaidas.