Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Lenguaje C

Multihilo C++

Multithreading es una forma especializada de multitarea y una multitarea es la característica que le permite a su computadora ejecutar dos o más programas simultáneamente. En general, hay dos tipos de multitarea:basada en procesos y basada en subprocesos.

La multitarea basada en procesos maneja la ejecución simultánea de programas. La multitarea basada en subprocesos se ocupa de la ejecución simultánea de partes del mismo programa.

Un programa multiproceso contiene dos o más partes que pueden ejecutarse simultáneamente. Cada parte de dicho programa se denomina subproceso, y cada subproceso define una ruta de ejecución separada.

C ++ no contiene ningún soporte integrado para aplicaciones de subprocesos múltiples. En su lugar, depende completamente del sistema operativo para proporcionar esta función.

Este tutorial asume que está trabajando en el sistema operativo Linux y que vamos a escribir un programa C ++ de subprocesos múltiples utilizando POSIX. POSIX Threads o Pthreads proporciona API que están disponibles en muchos sistemas POSIX similares a Unix, como FreeBSD, NetBSD, GNU/Linux, Mac OS X y Solaris.

Creación de hilos

La siguiente rutina se usa para crear un hilo POSIX −

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) 

Aquí, pthread_create crea un nuevo hilo y lo hace ejecutable. Esta rutina se puede llamar cualquier número de veces desde cualquier lugar dentro de su código. Aquí está la descripción de los parámetros −

Sr.No Parámetro y descripción
1

hilo

Un identificador opaco y único para el nuevo hilo devuelto por la subrutina.

2

atributo

Un objeto de atributo opaco que se puede usar para establecer atributos de subprocesos. Puede especificar un objeto de atributos de subproceso o NULL para los valores predeterminados.

3

start_routine

La rutina de C++ que ejecutará el subproceso una vez creado.

4

argumento

Un solo argumento que se puede pasar a start_routine. Debe pasarse por referencia como un puntero cast de tipo void. Se puede usar NULL si no se va a pasar ningún argumento.

El número máximo de subprocesos que puede crear un proceso depende de la implementación. Una vez creados, los subprocesos son pares y pueden crear otros subprocesos. No hay una jerarquía o dependencia implícita entre hilos.

Terminación de subprocesos

Existe la siguiente rutina que usamos para terminar un hilo POSIX −

#include <pthread.h>
pthread_exit (status) 

Aquí pthread_exit se utiliza para salir explícitamente de un hilo. Por lo general, se llama a la rutina pthread_exit() después de que un subproceso ha completado su trabajo y ya no es necesario que exista.

Si main() finaliza antes que los subprocesos que ha creado y sale con pthread_exit(), los otros subprocesos continuarán ejecutándose. De lo contrario, se terminarán automáticamente cuando finalice main().

Ejemplo

Este código de ejemplo simple crea 5 subprocesos con la rutina pthread_create(). Cada subproceso imprime un "¡Hola mundo!" y luego termina con una llamada a pthread_exit().

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
   long tid;
   tid = (long)threadid;
   cout << "Hello World! Thread ID, " << tid << endl;
   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   int rc;
   int i;
   
   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Compile el siguiente programa usando la biblioteca -lpthread de la siguiente manera −

$gcc test.cpp -lpthread

Ahora, ejecute su programa que da el siguiente resultado −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4

Pasar argumentos a subprocesos

Este ejemplo muestra cómo pasar varios argumentos a través de una estructura. Puede pasar cualquier tipo de datos en una devolución de llamada de hilo porque apunta a void como se explica en el siguiente ejemplo:

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

struct thread_data {
   int  thread_id;
   char *message;
};

void *PrintHello(void *threadarg) {
   struct thread_data *my_data;
   my_data = (struct thread_data *) threadarg;

   cout << "Thread ID : " << my_data->thread_id ;
   cout << " Message : " << my_data->message << endl;

   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   struct thread_data td[NUM_THREADS];
   int rc;
   int i;

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout <<"main() : creating thread, " << i << endl;
      td[i].thread_id = i;
      td[i].message = "This is message";
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Cuando el código anterior se compila y ejecuta, produce el siguiente resultado −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

Unir y separar hilos

Hay dos rutinas siguientes que podemos usar para unir o separar hilos:

pthread_join (threadid, status) 
pthread_detach (threadid) 

La subrutina pthread_join() bloquea el subproceso de llamada hasta que finaliza el subproceso 'threadid' especificado. Cuando se crea un subproceso, uno de sus atributos define si se puede unir o separar. Solo se pueden unir los subprocesos que se crean como unibles. Si un hilo se crea como separado, nunca se puede unir.

Este ejemplo demuestra cómo esperar a que se complete el subproceso mediante el uso de la rutina de unión Pthread.

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS 5

void *wait(void *t) {
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main () {
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], &attr, wait, (void *)i );
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // free attribute and wait for the other threads
   pthread_attr_destroy(&attr);
   for( i = 0; i < NUM_THREADS; i++ ) {
      rc = pthread_join(threads[i], &status);
      if (rc) {
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}

Cuando el código anterior se compila y ejecuta, produce el siguiente resultado −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.

Lenguaje C

  1. Operadores de C++
  2. Comentarios de C++
  3. Plantillas de clase de C++
  4. Descripción general de C++
  5. Constantes/Literales de C++
  6. Operadores en C++
  7. Números en C++
  8. Referencias de C++
  9. Plantillas C++
  10. Multihilo C++
  11. C# - Multiproceso