procesos proceso para obtener libreria lenguaje funcion estados ejemplos ejemplo creacion crea como c++ multithreading asynchronous concurrency

c++ - proceso - libreria para fork en c



¿Async siempre utiliza otro subproceso/núcleo/proceso en C++? (3)

Como sé, async ejecuta una función en otro hilo / proceso / núcleo y no bloquea el hilo principal, pero ¿es siempre el caso?

Tengo el siguiente código:

async(launch::async,[]() { Sleep(1000); puts("async"); }); puts("main");

Imprime async main , ¿eso significa que el hilo principal espera hasta que finalice la async ?

Si cambio a lo siguiente:

auto f = async(launch::async,[]() // add "auto f = " { Sleep(1000); puts("async"); }); puts("main");

Imprime la main async . Esto hace que parezca que main no espera que la async termine.


Como sé, async ejecuta una función en otro hilo / proceso / núcleo y no bloquea el hilo principal, pero ¿sucede siempre?

std::async está garantizado para ejecutarse en un hilo separado solo si se pasa std::launch::async como primer argumento:

  • std::launch::async : se inicia un nuevo hilo para ejecutar la tarea de forma asíncrona
  • std::launch::deferred la tarea se ejecuta en el hilo de llamada la primera vez que se solicita su resultado (evaluación diferida)

La política de lanzamiento predeterminada es std::launch::async | std::launch::deferred std::launch::async | std::launch::deferred .

std::async devuelve std::future . El destructor std::future se bloqueará solo si se devuelve el futuro de std::async :

estas acciones no se bloquearán para que el estado compartido esté listo, excepto que puede bloquear si todo lo siguiente es verdadero: el estado compartido fue creado por una llamada a std :: async, el estado compartido aún no está listo, y esto fue la última referencia al estado compartido

  • En su primer fragmento de código, crea una expresión rvalue que se destruye inmediatamente , por lo que "async" se imprimirá antes de "main" .

    1. La función anónima Async se crea y comienza a ejecutarse.

    2. La función anónima Async se destruye.

      • main ejecución main está bloqueada hasta que se complete la función.

      • "async" está impreso.

    3. main execucción main reanuda.

      • "main" está impreso.
  • En su segundo fragmento de código, crea una expresión lvalue cuya duración está vinculada a la variable f . f se destruirá al final del alcance de la función main ; por lo tanto, "main" se imprimirá antes de "async" debido al Delay(1000) .

    1. La función anónima Async se crea y comienza a ejecutarse.

      • Hay un Delay(1000) que retrasa la "async" de la impresión inmediata.
    2. main ejecución main continúa.

      • "main" está impreso.
    3. Fin del alcance principal.

    4. La función anónima Async se destruye.

      • main ejecución main está bloqueada hasta que se complete la función.

      • "async" está impreso.


Imprime async main , ¿eso significa que el hilo principal espera hasta que finalice la async ?

Sí, lo hace, pero eso se debe a que no captura el futuro devuelto de async . async es especial porque el future regresó de bloques en el destructor hasta que el hilo se completa. Ya que no captura el future devuelto

async(launch::async,[]() { Sleep(1000); puts("async"); });

debe finalizar antes de que se haga progreso en el hilo actual, ya que el future devuelto se destruye al final de la expresión.

Imprime la main async . Esto hace que parezca que main no espera que la async termine.

Que es lo que realmente quieres cuando llamas a async . Como ha capturado el futuro, su hilo principal puede continuar mientras se completa la tarea asincrónica. Como tiene un retraso en ese hilo, main se va a imprimir antes del hilo.


Si pasa std::launch::async , std::async debe ejecutar la tarea como si se ejecutara en su propio hilo.

El único concepto de enhebrar en C ++ es std::thread .

std::async devuelve un std::future con una propiedad única; si se destruye, se bloquea al completar la tarea almacenada en std::async . Esto lo atrapa cuando no puede capturar el valor de retorno; el std::future devuelto es un temporal sin nombre que aparece y se destruye al "final de esa línea".

Esta destrucción espera a que se complete la tarea async .

En el caso en que lo almacene, este retraso espera hasta que se destruya la variable f , que está al final de la línea main , que está después de que imprimimos.

Tenga en cuenta que al menos una implementación principal de C ++ 11, MSVC 2015 y 2017 tiene, en el mejor de los casos, marginalmente compatible std::async que usa un grupo de subprocesos en lugar de nuevos subprocesos. Este grupo de subprocesos significa que un conjunto de llamadas async de larga ejecución puede privar de la ejecución a otras llamadas async .

El uso de un grupo de subprocesos es legal (siempre que reproduzca cualquier subprocesos locales), pero debe evitar la inanición y crear nuevos subprocesos si todos los subprocesos existentes están ocupados durante "demasiado tiempo".

Es marginalmente compatible porque el estándar solo establece que los hilos "deberían" adelantar el progreso. Los hilos que nunca progresan por motivos aleatorios son legales bajo C ++; y en sentido podría argumentar que es lo que std::async emula en esos casos, pasando así la prueba de si-si.