es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Explicando los bloqueos con un solo candado desde “El Pequeño Libro de Go”: Los bloqueos, también conocidos como deadlocks, pueden ocurrir cuando múltiples goroutines (rutinas concurrentes de Go) necesitan acceder a un recurso compartido y cada una de ellas bloquea ese recurso con un solo candado. Imaginemos un escenario en el que una goroutine A bloquea un recurso con su candado mientras espera un resultado, pero esa goroutine no puede continuar ya que otra goroutine B también está esperando el mismo recurso. Dado que el candado ya está ocupado por la goroutine A, la goroutine B no puede acceder al recurso y se queda esperando. Ahora tenemos un deadlock, donde ninguna de las dos goroutines puede avanzar, resultando en un bloqueo del programa. Es importante tener en cuenta que este problema solo ocurre cuando se utiliza un solo candado para bloquear el recurso compartido.

Estoy leyendo El Pequeño Libro de Go.

En la página 76 se muestra cómo puedes generar un bloqueo con un solo bloqueo:

var (
    lock sync.Mutex
)

func main() {
    go func() { lock.Lock() }()
    time.Sleep(time.Millisecond * 10)
    lock.Lock()
}

Al ejecutar esto se produce un bloqueo como explica el autor. Sin embargo, lo que no entiendo es por qué.

Cambie el programa a esto:

var (
    lock sync.Mutex
)

func main() {
    go func() { lock.Lock() }()
    lock.Lock()
}

Mi expectativa era que aún se produjera un bloqueo. Pero no fue así.

¿Alguien podría explicarme qué está sucediendo aquí, por favor?

La única situación que se me ocurre que podría explicar esto es la siguiente (pero esto es especulación):

Primer ejemplo:

  1. Se adquiere el bloqueo en la primera goroutine.
  2. La llamada a time.Sleep() asegura que se adquiera el bloqueo.
  3. La función main intenta adquirir el bloqueo, lo que genera un bloqueo.
  4. El programa termina.

Segundo ejemplo:

  1. Se adquiere el bloqueo en la primera goroutine, pero esto lleva un tiempo en ocurrir (??).
  2. Dado que no hay demora, la función main adquiere el bloqueo antes de que la goroutine pueda hacerlo.
  3. El programa termina.
Tags:  ,

Answer

  1. Avatar for davy.ai

    En el primer ejemplo, la llamada a time.Sleep asegura que la goroutine creada en la función main comience a ejecutarse antes de la llamada a lock.Lock(). Esto significa que la goroutine adquiere el bloqueo primero y luego espera indefinidamente, evitando que la función principal adquiera el bloqueo y resultando en un bloqueo.

    En el segundo ejemplo, no hay retraso antes de la llamada a lock.Lock(), por lo que es posible que la función principal adquiera el bloqueo antes que la goroutine. Si esto sucede, la goroutine esperará indefinidamente para adquirir el bloqueo, pero dado que el bloqueo ya está en manos de la función principal, no habrá un bloqueo.

    Es importante tener en cuenta que confiar en el tiempo de ejecución de las goroutines no es una forma confiable de prevenir bloqueos, y en general es mejor utilizar un enfoque más explícito como usar un sync.WaitGroup para asegurarse de que todas las goroutines hayan terminado antes de salir del programa.

Comments are closed.