He estado utilizando el mecanismo de comunicación basado en la cola de producción-consumidor, según lo sugerido por asveikau, durante décadas sin ningún problema específicamente relacionado con multiThreading. Hay algunas ventajas:
1) Las instancias 'hiloCommClass' pasadas en la cola a menudo pueden contener todo lo necesario para que el hilo haga su trabajo: miembro/s para datos de entrada, miembro/s para datos de salida, métodos para el Hilo para llamar para hacer el trabajo, en algún lugar para poner cualquier mensaje de error/excepción y un evento 'returnToSender (this)' para llamar, así que devolver algo al solicitante por algún thread-safe significa que el hilo de trabajo no necesita saber. El subproceso de trabajo se ejecuta asincrónicamente en un conjunto de datos totalmente encapsulados que no requiere bloqueo. 'returnToSender (this)' podría poner el objeto en cola en otra cola P-C, podría PostMessage en una secuencia de la interfaz gráfica de usuario, podría liberar el objeto a una agrupación o simplemente eliminarlo(). Lo que sea que haga, el hilo de trabajo no necesita saberlo.
2) No es necesario que el subproceso solicitante sepa nada sobre qué subproceso hizo el trabajo; todo lo que el solicitante necesita es una cola para continuar. En un caso extremo, el hilo de trabajo en el otro extremo de la cola puede serializar los datos y comunicarlos a otra máquina a través de una red, solo llamando a returnToSender (esto) cuando se recibe una respuesta de red - el solicitante no necesita saber esto detalle: solo que el trabajo ya está hecho.
3) Generalmente, es posible organizar las instancias 'threadCommsClass' y las colas para que sobrevivan tanto el hilo del solicitante como el hilo del trabajador. Esto alivia esos problemas cuando el solicitante o el trabajador terminan y se deshacen() antes que el otro, ya que no comparten datos directamente, no puede haber AV/lo que sea. Esto también destruye todos los 'No puedo detener mi hilo de trabajo porque está atorado en un API de bloqueo'. ¿Por qué molestarse en detenerlo si puede quedar huérfano y dejarlo morir sin posibilidad de escribir algo liberado?
4) Un threadpool se reduce a un bucle de una línea para crear varios hilos de trabajo y les pasa la misma cola de entrada.
5) El bloqueo está restringido a las colas. Cuantos más mutexes, condVars, secciones críticas y otros bloqueos sincronizados hay en una aplicación, más difícil es controlarlo todo y mayor es la posibilidad de un interbloqueo intermitente que es una pesadilla para depurar. Con los mensajes en cola, (idealmente), solo la clase de cola tiene bloqueos. La clase de cola debe funcionar al 100% con varios productores/consumidores, pero esa es una clase, no una aplicación llena de bloqueo descoordinado (¡yech!).
6) Un threadCommsClass se puede elevar en cualquier momento, en cualquier lugar, en cualquier hilo y se puede colocar en una cola. Ni siquiera es necesario que el código del solicitante lo haga directamente, por ej. una llamada a un método de clase de registrador, 'myLogger.logString ("Operación completada con éxito");' podría copiar la cadena en un objeto de comunicación, ponerla en cola hasta el hilo que realiza la escritura de registro y devolver 'inmediatamente'. Luego, depende de la secuencia de la clase de registrador manejar los datos de registro cuando los dequeue - puede escribirlos en un archivo de registro, puede encontrar después de un minuto que el archivo de registro es inalcanzable debido a un problema de red. Puede decidir que el archivo de registro es demasiado grande, archivarlo e iniciar otro. Puede escribir la cadena en el disco y luego PostMessage la instancia de threadCommsClass en un hilo de la GUI para mostrar en una ventana de terminal, lo que sea. No tiene importancia para el hilo que solicita el registro, que simplemente continúa, como lo hacen los otros hilos que han solicitado el registro, sin un impacto significativo en el rendimiento.
7) Si necesita matar un hilo esperando en una cola, en lugar de esperar a que el sistema operativo lo mate en la aplicación, solo póngalo en cola y diga que termine.
seguramente hay desventajas:
1) Empujando datos directamente en los miembros de hilo, lo que indica que se ejecute y esperando a que termine es más fácil de entender y será más rápido, en el supuesto de que el hilo no tiene por qué ser creado cada vez
2) Operación realmente asíncrona, donde el hilo se pone en cola algún trabajo y, algún tiempo después, lo devuelve al llamar a un controlador de eventos que tiene que comunicar los resultados, es más difícil de manejar para los desarrolladores utilizados para el código de un solo subproceso y a menudo requiere un diseño de tipo de máquina de estado en el que los datos de contexto se deben enviar en threadCommsClass para que se puedan tomar las acciones correctas cuando vuelvan los resultados. Si hay un caso ocasional en el que el solicitante solo tiene que esperar, puede enviar un evento en el threadCommsClass que se señala mediante el método returnToSender, pero esto es obviamente más complejo que simplemente esperar a que termine algún manejador de subprocesos.
Independientemente del diseño que se use, olvide las simples variables globales como lo han expresado otros carteles. Hay un caso para algunos tipos globales en las comunicaciones de subprocesos; uno que uso muy a menudo es un grupo seguro de subprocesos de instancias de threadCommsClass (esto es solo una cola que se llena previamente con objetos). Cualquier hilo que desee comunicarse tiene que obtener una instancia de threadCommsClass del grupo, cargarla y ponerla en cola. Cuando termina la comunicación, el último subproceso que se usa lo libera al grupo.Este enfoque evita el nuevo fugitivo(), y me permite monitorear fácilmente el nivel del grupo durante la prueba sin ningún administrador de memoria complejo (por lo general, volcar el nivel del grupo a una barra de estado cada segundo con un temporizador). Los objetos que se escapan, (el nivel baja) y los objetos de doble liberación (el nivel sube) se detectan fácilmente y se arreglan.
multihilo puede ser seguro y entregar aplicaciones escalable y de alto rendimiento que son casi un placer para mantener/mejorar, (casi :), pero hay que despedir a las variables globales simples - tratarlos como Tequila - rápido y fácil por ahora, pero sabes que te volarán la cabeza mañana.
¡Buena suerte!
Martin
Una vez más, las personas intentan cerrar las preguntas porque son preguntas para principiantes. Trate de recordar que alguna vez fue un principiante. –