Entendiendo el modelo de memoria de Go
Un truco aparentemente inteligente para evitar el bloqueo en código C concurrente es el siguiente: tengo una variable global ptr
que apunta a un mystruct
y quiero actualizar esa estructura. Así que asignaré un nuevo mystruct
, completaré los datos en y solo entonces haré que el cambio sea visible para el mundo señalando ptr
al nuevo objeto mystruct
.
Esto es incorrecto ya que depende del orden de las escrituras y no hay garantía de que la escritura en ptr
sea visible para otros subprocesos después de que todas las tiendas en el nuevo mystruct
hayan tomado lugar. Por lo tanto, el nuevo objeto mystruct
se puede devolver parcialmente inicializado.
Mi pregunta es: ¿esto también puede suceder en Go? Creo que sí, pero tengo que decir que El modelo de memoria Go me resulta un poco incomprensible.
Escribí un poco de código Go para probarlo, pero en mi máquina, el mal comportamiento no se manifiesta:
package main
import (
"fmt"
"time"
)
type mystruct struct {
a int
b int
}
var (
ptr *mystruct
counter int
)
func writer() {
for {
counter += 1
s := mystruct{a: counter, b: counter}
ptr = &s
}
}
func reader() {
time.Sleep(time.Millisecond)
for {
if ptr.a != ptr.b {
fmt.Println("Oh no, I'm so buggy!")
}
}
}
func main() {
go writer()
go reader()
select {}
}
Esto, por supuesto, no prueba nada.
¿Puede proporcionarnos una comparación muy breve de las garantías de memoria proporcionadas por las goroutines de Go con (casi ninguna garantía) proporcionadas por un subproceso POSIX en C?
Mostrar la mejor respuesta