Latest web development tutorials

El multithreading C ++

Multihilo es una forma especializada de la multitarea, la multitarea permite dejar que el ordenador funcione dos o más programas. En general, dos tipos de multitarea: basado en procesos y subprocesos basan.

  • programa multitarea basado en procesos se ejecuta al mismo tiempo.
  • multitarea basado en threads de procesamiento es la ejecución concurrente del mismo fragmento de programa.

multiproceso programa contiene dos o más partes que se pueden ejecutar simultáneamente. Tal programa para cada parte se llama un hilo, cada hilo define una vía separada de ejecución.

C ++ no incluye ningún tipo de apoyo integrado para aplicaciones de subprocesos múltiples. En cambio, es totalmente dependiente del sistema operativo para proporcionar esta funcionalidad.

Este tutorial asume que está utilizando el sistema operativo Linux, queremos usar POSIX escribir multiproceso programa en C ++. API de hilos POSIX o Pthreads se puede proporcionar en múltiples tipos de sistemas Unix POSIX disponibles, tales como FreeBSD, NetBSD, GNU / Linux, Mac OS X y Solaris.

Crear un hilo

El siguiente programa, podemos utilizarlo para crear un de los hilos POSIX:

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

Aquí, pthread_create crea un nuevo hilo y que sea ejecutable.La siguiente es una descripción de los parámetros:

参数 描述
thread 指向线程标识符指针。
attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。
start_routine 线程运行函数起始地址,一旦线程被创建就会执行。
arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。

Cuando se crea un hilo éxito, la función devuelve 0, si el valor de retorno de 0 indica que no pudo crear hilo.

Terminar el hilo

Utilice el siguiente procedimiento, podemos utilizarlo para poner fin a los hilos POSIX:

#include <pthread.h>
pthread_exit (status) 

Aquí, pthread_exit utilizarse para salir de un hilo.En circunstancias normales, la función pthread_exit () se llama cuando el trabajo sin tener que seguir existiendo después de que el hilo.

Si el main () antes de que el extremo del hilo que se ha creado, y sale a través pthread_exit (), y luego los otros hilos se continuarán ejecutando. De lo contrario, van a estar en el main () al final se termina automáticamente.

Ejemplos

El siguiente código de ejemplo sencillo utiliza pthread_create () crea cinco hilos, cada salida "Hola w3big!":

#include <iostream>
// 必须的头文件是
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

// 线程的运行函数
void* say_hello(void* args)
{
    cout << "Hello w3big!" << endl;
}

int main()
{
    // 定义线程的 id 变量,多个变量使用数组
    pthread_t tids[NUM_THREADS];
    for(int i = 0; i < NUM_THREADS; ++i)
    {
        //参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
        int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
        if (ret != 0)
        {
           cout << "pthread_create error: error_code=" << ret << endl;
        }
    }
    //等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
    pthread_exit(NULL);
}

Utilice la biblioteca -lpthread compilado el siguiente programa:

$ g++ test.cpp -lpthread -o test.o

Ahora, la ejecución del programa producirá los siguientes resultados:

$ ./test.o
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!
Hello w3big!

El siguiente código de ejemplo sencillo utiliza pthread_create () crea cinco hilos, y recibir parámetros de entrada. Cada hilo imprime un "Hola w3big!" Mensaje, y da salida a los parámetros recibidos, y luego llamar a pthread_exit () termina el hilo.

//文件名:test.cpp

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

using namespace std;

#define NUM_THREADS     5

void *PrintHello(void *threadid)
{  
   // 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
   int tid = *((int*)threadid);
   cout << "Hello w3big! 线程 ID, " << tid << endl;
   pthread_exit(NULL);
}

int main ()
{
   pthread_t threads[NUM_THREADS];
   int indexes[NUM_THREADS];// 用数组来保存i的值
   int rc;
   int i;
   for( i=0; i < NUM_THREADS; i++ ){      
      cout << "main() : 创建线程, " << i << endl;
      indexes[i] = i; //先保存i的值
      // 传入的时候必须强制转换为void* 类型,即无类型指针        
      rc = pthread_create(&threads[i], NULL, 
                          PrintHello, (void *)&(indexes[i]));
      if (rc){
         cout << "Error:无法创建线程," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Ahora compilar y ejecutar el programa producirá los siguientes resultados:

$ g++ test.cpp -lpthread -o test.o
$ ./test.o
main() : 创建线程, 0
main() : 创建线程, 1
main() : 创建线程, 2
main() : 创建线程, 3
main() : 创建线程, 4
Hello w3big! 线程 ID, 4
Hello w3big! 线程 ID, 3
Hello w3big! 线程 ID, 2
Hello w3big! 线程 ID, 1
Hello w3big! 线程 ID, 0

Pasar parámetros a un hilo

Este ejemplo demuestra cómo pasar varios parámetros de la estructura. Puede pasar cualquier tipo de datos en la devolución de llamada hilo, porque apunta al vacío, como se muestra en los siguientes ejemplos:

#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 se compila y ejecuta, produce los siguientes resultados:

$ g++ -Wno-write-strings test.cpp -lpthread -o test.o
$ ./test.o
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

Conexión y separar hilo

Podemos usar las dos funciones siguientes para conectar o hilos separados:

pthread_join (threadid, status) 
pthread_detach (threadid) 

pthread_join () subrutina obstaculizar el programa de llamada hasta que el hilo threadid especificada termina. Cuando se crea un hilo, es un atributo define si se conecta (se pueden unir) o desmontable (individual). Definir sólo para crear un hilo que puede ser conectado puede ser conectado. Si un hilo se crea se define como separables, nunca se puede conectar.

Este ejemplo muestra cómo utilizar la función pthread_join () para esperar a la finalización de rosca.

#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;

   // 初始化并设置线程为可连接的(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], NULL, wait, (void *)i );
      if (rc){
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // 删除属性,并等待其他线程
   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 se compila y ejecuta, produce los siguientes resultados:

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 : 4  ...exiting 
Sleeping in thread 
Thread with id : 3  ...exiting 
Sleeping in thread 
Thread with id : 2  ...exiting 
Sleeping in thread 
Thread with id : 1  ...exiting 
Sleeping in thread 
Thread with id : 0  ...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.