2011-06-02 18 views
9

Tengo un trabajador std::thread y quiero que su lazo principal compruebe si algún otro hilo le dice que deje de dar vueltas y salir.
¿Cuál es una buena forma de plataforma cruzada para hacer esto? ¿El impulso proporciona algún objeto de evento para ello?
¿Está utilizando solo un bool considerado seguro para subprocesos?deteniendo con gracia un std :: hilo?

+0

¿Qué quiere decir con “el uso de” aquí? En general, la respuesta siempre es "no": ningún tipo excepto "atomic" es inherentemente seguro para subprocesos. –

+0

Los bloqueos ('std :: mutex') no son apropiados para esto. Desafortunadamente, C++ 0x no hereda 'boost :: thread :: interrupt', lo cual es una gran lástima. Ver [estos] (http://stackoverflow.com/questions/2845704/how-to-interrupt-a-waiting-c0x-thread) [two] (http://stackoverflow.com/questions/2790346/c0x-thread -interrupción) preguntas. –

+1

@Tomalak: explique el problema con el uso de un mutex. Parece la solución más fácil y más obvia. –

Respuesta

7

.. así que depende. ¿Qué está haciendo el hilo? ¿Bloquea algo, E/S, sleep o alguna otra API?

Si es sólo la CPU-looping todo el tiempo y no importa sobre exactamente cuando se detiene y que se detenga y salidas, a continuación, sólo tiene que utilizar un valor lógico. No tiene sentido, en este caso, bloquear un booleano 'stopAndExit'.

Si el subproceso de trabajo no lo lee como verdadero en un bucle cuando tal vez debería, debido a la falta de atomicidad, lo obtendrá la próxima vez. ¿Por qué realizar bloqueos/llamadas API cuando no es necesario? Una llamada de nivel de kernel por parte del usuario para adquirir/liberar un objeto de sincronización tardará años en comparación con una simple 'salida if (stop);', desperdiciando tiempo en cada bucle que podría haberse utilizado para el cálculo, o lo que sea que haga en su CPU hilo enlazado

Es multiplataforma

Saludos, Martin

+3

+1 Para hacer que la gente piense si realmente son necesarios métodos de sincronización costosos el tiempo. –

+9

No veo cómo se puede garantizar que esto funcione. ¿No es una optimización válida para un compilador almacenar en caché el valor de una variable en un registro si no hay barrera de memoria o semántica de lectura volátil? En ese caso, nunca verá la actualización. Puedo decirte que este tipo de problema ** definitivamente ** existe en .NET (es posible que un programa de subprocesos múltiples entre en un bucle infinito si comprueba constantemente una condición de bool, incluso si ahora el valor es realmente ' true' porque se actualizó desde otro subproceso). – bobbymcr

+0

@bobbymcr - pruébelo con cualquier cosa que no sea un hilo tremendamente trivial, diseñado específicamente para mostrar este problema. No sucederá en Intel, no sucederá en Spark, no sucederá en nada que haya usado alguna vez. No sucederá porque los registros se derraman en la memoria caché L1 en una interrupción del controlador, en una llamada de función, si respira demasiado fuerte. –

2

Lo que podría tener es un std :: mutex que se comparte entre el hilo primario y su hilo trabajador.

Su hilo de trabajo puede adquirir std :: mutex :: try_lock antes de comenzar cualquier trabajo y liberarlo intermitentemente. El hilo principal puede bloquear este mutex cuando quiere que se cierre el hilo de trabajo. Su hilo de trabajo puede detectar esto usando try_lock y salir

+4

¿Beneficio de rendimiento posible para revertirlo? El subproceso principal se mantiene en el bloqueo, el subproceso de trabajo intenta (sin bloqueo) adquirirlo al comienzo del ciclo, sale cuando tiene éxito. Ahorra ciclos de liberación cada vez, y el hilo principal no tiene que quedarse esperando que termine un ciclo si tiene otras cosas que hacer. –

0

std :: mutex y sus parientes son los mecanismos principales. std :: lock_guard y unique_lock se basan en esto, y std :: condition_variable son buenos para este propósito.

0

Como mencionaste boost, hay boost :: thread que puedes usar.

En su caso, después de iniciar un hilo, puede interrumpirlo utilizando el método de interrupción(). El hilo del receptor puede verificar las solicitudes de interrupción con el método boost :: this_thread :: interruption_point(). Esto hará que el hilo salga si hay una solicitud de interrupción, de lo contrario, la ignorará.

se puede comprobar la documentación aquí: Boost Thread Documentation

+0

Tenga en cuenta que std :: thread se basa en el diseño de hilos de Boost [link] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2184.html - así que podría decirse que el std ser más portátil (aunque actualmente es probable que haya poca diferencia en las plataformas admitidas). – holtavolt

+2

El hilo std :: tenía 'interrupt' eliminado de él. :-( –

+0

@Howard ¿Por casualidad sabe por qué fue eliminado, o tal vez aún más atroz: por qué C++ 14/17 todavía no lo tiene? – rubenvb

Cuestiones relacionadas