Multithreading C ++
Multithreading é uma forma especializada de multi-tasking, multi-tasking permite deixar o computador funcionar dois ou mais programas. Em geral, dois tipos de multitarefa: baseado em processos e fio-based.
- programa multitarefa baseada no processo é executado simultaneamente.
- multitasking baseado no segmento de processamento é a execução simultânea do mesmo fragmento de programa.
programa multithread contém duas ou mais partes que podem ser executados simultaneamente. Tal programa para cada parte é chamada de segmento, cada thread define um caminho separado da execução.
C ++ não inclui qualquer suporte embutido para aplicações multi-threaded. Em vez disso, é totalmente dependente do sistema operacional para fornecer essa funcionalidade.
Este tutorial assume que você está usando o sistema operacional Linux, nós queremos usar POSIX escrever programa multithread C ++. API POSIX Threads ou Pthreads podem ser fornecidos em vários tipos de sistemas Unix POSIX disponíveis, tais como FreeBSD, NetBSD, GNU / Linux, Mac OS X e Solaris.
Criar um fio
O programa a seguir, podemos usá-lo para criar um POSIX tópicos:
#include <pthread.h> pthread_create (thread, attr, start_routine, arg)
Aqui, pthread_create cria um novo segmento e torná-lo executável.O seguinte é uma descrição dos parâmetros:
参数 | 描述 |
---|---|
thread | 指向线程标识符指针。 |
attr | 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。 |
start_routine | 线程运行函数起始地址,一旦线程被创建就会执行。 |
arg | 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。 |
Quando um segmento é criado com êxito, a função retorna 0, se o valor de retorno de 0 indica que não conseguiu criar discussão.
Terminar a thread
Use o procedimento a seguir, podemos usá-lo para encerrar um POSIX tópicos:
#include <pthread.h> pthread_exit (status)
Aqui, pthread_exit usada para sair explicitamente um fio.Em circunstâncias normais, a função pthread_exit () é chamado quando o trabalho feito sem ter de continuar a existir após a discussão.
Se o main () antes do final do segmento que criou, e sai através pthread_exit (), em seguida, os outros segmentos continuará a executar. Caso contrário, eles serão, no essencial () no final é automaticamente terminada.
Exemplos
O seguinte código exemplo simples usa pthread_create () função cria cinco linhas, cada saída "Olá 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); }
Use biblioteca -lpthread compilado o seguinte programa:
$ g++ test.cpp -lpthread -o test.o
Agora, a implementação do programa irá produzir os seguintes resultados:
$ ./test.o Hello w3big! Hello w3big! Hello w3big! Hello w3big! Hello w3big!
O seguinte código exemplo simples usa pthread_create () função cria cinco tópicos, e receber parâmetros de entrada. Cada segmento imprime uma "Olá w3big!" Mensagem, e emite os parâmetros recebidos, e depois chamar pthread_exit () termina o segmento.
//文件名: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); }
Agora compilar e executar o programa irá produzir os seguintes 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
Passar parâmetros para um Tópico
Este exemplo demonstra como passar múltiplos estrutura de parâmetros. É possível transmitir qualquer tipo de dados no retorno de chamada rosca, uma vez que aponta para o vazio, como mostrado nos exemplos seguintes:
#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); }
Quando o código acima é compilado e executado, ele produz os seguintes 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
Ligar e separação de fio
Nós podemos usar as duas funções seguintes para ligar ou segmentos separados:
pthread_join (threadid, status) pthread_detach (threadid)
pthread_join () sub-rotina prejudicar o programa de chamada até que o segmento ThreadID especificado termina. Quando você cria um segmento, é um atributo define se ele está conectado (acopláveis) ou destacável (independente). Definir apenas criar um segmento que pode ser conectado pode ser conectado. Se um segmento é criado é definido como separável, ele nunca pode ser conectado.
Este exemplo demonstra como utilizar a função pthread_join () para aguardar o segmento conclusão.
#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); }
Quando o código acima é compilado e executado, ele produz os seguintes 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.