Pregunta

En mi código hay tres rutinas concurrentes. Intento dar una breve descripción de mi código,

Routine 1 {
do something

*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 2 {
do something

*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 3 {
do something

*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*

do something
}

main {
routine1
routine2
routine3
}

Quiero eso, mientras que los códigos entre dos hacen algo (códigos entre dos marcas de estrellas) se está ejecutando, el flujo de control no debe ir a otras rutinas GO. Por ejemplo, cuando la rutina1 está ejecutando los eventos entre dos estrellas (eventos de envío e impresión), la rutina 2 y 3 debe bloquearse (los medios de ejecución no pasa a la rutina 2 o 3 de la rutina 1). Después de completar el último evento de impresión, El flujo de ejecución puede pasar a la rutina 2 o 3. ¿Alguien puede ayudarme especificando, cómo puedo lograr esto? ¿Es posible implementar la especificación anterior de WaitGroup? ¿Alguien puede mostrarme dando un ejemplo simple sobre cómo implementar el ejemplo especificado anteriormente usando WaitGroup? Gracias.

NB: puede ser que esta sea una pregunta repetida de este. Sin embargo, intenté usar ese mecanismo de sincronización de bloqueo porque tengo un código grande, por eso no pude poner el bloqueo de bloqueo correctamente, y está creando una situación de punto muerto (o puede ser mi método es Error a producir). ¿Alguien puede ayudarme con un procedimiento simple, por lo tanto, puedo lograr esto? Doy un ejemplo simple de mi código aquí donde aquí quiero poner dos impresiones y enviar un evento dentro de Mutex (para la rutina 1), por lo que la rutina 2 no puede interrumpirlo. ¿Puedes ayudarme cómo es posible? Una posible solución dada,http://play.golang.org/p/-uoqsqbjks que da error.

¿Fue útil?

Solución

¿Por qué quieres hacer esto?

El problema de punto muerto es que si no permite que se programen otras goroutinas, entonces sus envíos de canal no pueden continuar, a menos que haya un almacenamiento en búfer. Los canales de GO tienen amortiguación finita, por lo que terminas con una condición de carrera sobre el drenaje antes de que los envíen mientras están llenos. Puede introducir infinito amortiguación, o enviar cada uno de los envíos, pero nuevamente se reduce a: ¿Por qué está tratando de hacer esto? ¿Qué estás intentando lograr?

Otra cosa: si solo desea asegurar la exclusión mutua de los tres conjuntos de código entre *s, entonces sí, puede usar mutexes. Si quieres asegurarte de que no El código interrumpe su bloque, independientemente de dónde se suspendiera, entonces es posible que necesite usar RunTime.LockOSThread y Runtime.unlockostThread. Estos son de nivel bastante bajo y necesitas saber qué estás haciendo, y rara vez son necesarios. De ustedes quiere que no haya otras goroutinas en ejecución, tendrá que tener tiempo de ejecución.gomaxprocs (1), que actualmente es el valor predeterminado.

Otros consejos

El problema al responder a su pregunta es que parece que nadie entiende cuál es realmente su problema. Veo que estás preguntando repetidamente sobre aproximadamente lo mismo, aunque no se han hecho ningún progreso. No hay ofensa al decir esto. Es un intento de ayudarlo mediante una sugerencia para reformular su problema de una manera comprensible para los demás. Como posible efecto secundario agradable, algunos problemas se resuelven a sí mismos mientras se explican a otros de una manera comprensible. He experimentado eso muchas veces solo.

Otra pista podría estar en la mezcla sospechosa de sincronización explícita y comunicación de canales. Eso no significa que el diseño esté necesariamente roto. Simplemente no sucede en un caso típico/simple. Una vez más, su problema puede ser atípico/no trivial.

Quizás de alguna manera es posible rediseñar su problema usando solo canales. En realidad, creo que cada problema que involucra sincronización explícita (en GO) podría codificarse mientras usa solo canales. Dicho esto, es cierto que algunos problemas están escritos con sincronización explícita muy fácilmente. Además, la comunicación de canal, tan barata como es, no es tan barata como la mayoría de las primitivas de sincronización. Pero eso podría ser atendido más tarde, cuando funciona el código. Si el "patrón" para algunos dice que Sync.Mutex surgirá visiblemente en el código, debería ser posible cambiar a él y mucho más fácil de hacerlo cuando el código ya funciona y, con suerte, tiene pruebas para ver sus pasos mientras realiza los ajustes. .

Trate de pensar en sus goroutinas como agentes de actuación independientes que:

  • Poseer exclusivamente los datos recibidos del canal. El idioma no aplicará esto, debe desplegar la disciplina de Own.
  • Ya no toque los datos que han enviado a un canal. Se deduce de la primera regla, pero lo suficientemente importante como para ser explícito.
  • Interactuar con otros agentes (Goroutinas) por tipos de datos, que encapsulan una unidad completa de flujo de trabajo/cálculo. Esto elimina, por ejemplo, su lucha anterior para obtener el número correcto de mensajes de canal antes de que se complete la "unidad".
  • Por cada canal que usan debe ser absolutamente claro antes Si el canal debe ser sin toparse, debe ser amortiguado para un número fijo de elementos o si puede estar sin consolidar.
  • No tiene que pensar (saber) lo que otros agentes están haciendo anteriormente recibiendo un mensaje de ellos si eso es necesario para que el agente haga su propia tarea, parte de la imagen más grande.

Con suerte, usar tan pocas reglas generales debe producir código que sea más fácil de razonar y que generalmente no requiere ninguna otra sincronización. (Estoy ignorando intencionalmente los problemas de rendimiento de las aplicaciones de misión crítica ahora).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top