-
Notifications
You must be signed in to change notification settings - Fork 5
Threads
Os códigos descritos nesse tópico são referentes à seção de threads.
Podem ser encontrados tanto aqui quanto nesse link.
Visualizar o tid da thread
Código:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
void* funcao_thread(void* arg)
{
printf("\tNova thread criada com PID %d e TID %d\n",
getpid(), gettid());
sleep(50);
printf("Thread com o ID %d finalizada.\n", gettid());
return NULL;
}
int main()
{
pthread_t thread1, thread2;
printf("Processo pesado PID %d\n", getpid());
pthread_create(&thread1, NULL, &funcao_thread, NULL);
pthread_create(&thread2, NULL, &funcao_thread, NULL);
//printf("Identificador da thread %lu\n",thread1);
//printf("Identificador da thread %lu\n",thread2);
sleep(20);
printf("Main finalizando\n");
return 0;
}Compilar e Executar:
gcc -pthread exemplo_pthread.c -o exemplo_pthread
./exemplo_pthreadNesse exemplo, serão criadas duas threads usando o pthread_create, que executarão duas instâncias da função funcao_thread.
Note
Não serão criados dois processos novos, como acontece usando o fork. Sendo assim, será o mesmo processo, mas executando duas instâncias da função que ainda compartilham os mesmos dados, e o mesmo código.
Cada uma das threads vai imprimir no terminal o PID do processo e o TID, o ID da thread, após isso, a chamada da função sleep(50), faz com que as duas fiquem em pausa por 50 segundos.
É importante notar que nesse exemplo, o programa vai esperar apenas 20 segundos, por conta do sleep(20) que está depois das duas pthread_create que se encontram no main.
Exemplo de saída:
Processo pesado PID 28910
Nova thread criada com PID 28910 e TID 28911
Nova thread criada com PID 28910 e TID 28912
Main finalizandoIsso significa que as threads não terão tempo de serem concluídas, pois após 20 segundos o programa acaba e as threads são encerradas, isso pode ser notado no exemplo de saída, o segundo print que está presente na função das threads não foi executado. Pois o main não vai esperar as threads finalizarem ao menos que isso seja indicado. Para isso, assim como no fork tínhamos o wait(0), para threads temos o pthread_join, assim o main só irá finalizar quando todas as threads forem finalizadas.
Código modificado com o pthread_join:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
void* funcao_thread(void* arg)
{
printf("\tNova thread criada com PID %d e TID %d\n",
getpid(), gettid());
sleep(50);
printf("Thread com o ID %d finalizada.\n", gettid());
return NULL;
}
int main()
{
pthread_t thread1, thread2;
printf("Processo pesado PID %d\n", getpid());
pthread_create(&thread1, NULL, &funcao_thread, NULL);
pthread_create(&thread2, NULL, &funcao_thread, NULL);
//printf("Identificador da thread %lu\n",thread1);
//printf("Identificador da thread %lu\n",thread2);
sleep(20);
printf("Main esperando as threads finalizarem\n");
// aguardando as threads finalizarem
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Main finalizando\n");
return 0;
}Compilar e Executar:
gcc -pthread exemplo_thread.c -o exemplo_thread
./exemplo_threadExemplo de saída:
Processo pesado PID 7167
Nova thread criada com PID 7167 e TID 7168
Nova thread criada com PID 7167 e TID 7169
Main esperando as threads finalizarem
Thread com o ID 7169 finalizada.
Thread com o ID 7168 finalizada.
Main finalizandoCom essa modificação, o main esperou as duas threads finalizarem para então continuar a execução, isso pode ser observado na saída do programa onde o conteúdo do segundo print que estava na função funcao_thread apareceu no terminal, sinalizando que as threads terminaram de executar, diferentemente do exemplo anterior que não tínhamos usado o pthread_join.
Note
Nesse exemplo de saída é interessante notar que foi criada primeiramente uma thread com o ID 7168, e outra com o ID 7169, elas foram criadas nessa ordem, mas quando elas foram finalizar podemos notar que primeiro finalizou a com o ID 7169 e depois a de ID 7168, porque isso aconteceu?
Mostra a execução "simultânea" de duas threads
Código:
#include <pthread.h>
#include <stdio.h>
void * ProcessoLeve1()
{
int i;
printf("T1\n");
for (i = 1; i < 100000; i++)
//for (i = 1; i < 100; i++)
printf("\tThread 1 - %d\n",i);
}
void * ProcessoLeve2()
{
int i;
printf("T2\n");
for (i = 100000; i < 200000; i++)
//for (i = 100; i < 200; i++)
printf("\t\tThread 2 - %d\n",i);
}
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, ProcessoLeve1, NULL);
pthread_create(&thread2, NULL, ProcessoLeve2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_detach(thread1);
pthread_detach(thread2);
return 0;
}Compilar e Executar:
gcc -pthread concorrentes.c -o concorrentes
./concorrentesNesse exemplo, também são criadas duas threads com o pthread_create para executar duas funções diferentes: ProcessoLeve1 e ProcessoLeve2.
O ProcessoLeve1 apenas imprime na tela: Thread 1 - i, onde i é incrementado de 1 até 99999.
O ProcessoLeve2 apenas imprime na tela: Thread 2 - i, onde i é incrementado de 100000 até 199999.
Exemplo de saída:
T2
Thread 2 - 100000
Thread 2 - 100001
Thread 2 - 100002
...
Thread 2 - 100010
Thread 2 - 100011
Thread 2 - 100012
T1
Thread 2 - 100013
Thread 1 - 1
Thread 1 - 2
Thread 1 - 3
Thread 1 - 4
Thread 2 - 100014
Thread 1 - 5
Thread 2 - 100015
Thread 1 - 6
Thread 1 - 7
Thread 2 - 100016
Thread 1 - 8
Thread 1 - 9
Thread 2 - 100017
Thread 1 - 10
Thread 2 - 100018
Thread 2 - 100019
Thread 2 - 100020
Thread 2 - 100021
Thread 1 - 11
Thread 2 - 100022
Thread 1 - 12
Thread 1 - 13
Thread 1 - 14
Thread 2 - 100023
Thread 1 - 15
Thread 2 - 100024
Thread 1 - 16
Thread 1 - 17
Thread 1 - 18
Thread 2 - 100025Ao executar o código, é possível notar que os dois prints das funções são executados aleatoriamente. Pode ser que seja impresso 7 da thread1 e 4 da thread2 por vez. Ou 6 da thread1 e 20 da thread2, não tem como prever. Nesse exemplo de saída se encontra as primeiras linhas que foram geradas pelo programa, podemos notar que a thread dois conseguiu acesso primeiro ao processador do que a thread um.
Isso acontece porque as duas threads criadas estão concorrendo pelo processador.
Cada thread quer usar os recursos do processador para executar e finalizar a sua tarefa, mas não só elas como também todos os outros processos que estão sendo executados no computador. Isso leva à execução alternada e completamente aleatória das duas funções.
Note
Isso também aconteceu no exemplo anterior, todas as threads e processos concorrem pelo uso do processador, por isso a thread com o ID 7169 terminou antes da outra de ID 7168 que foi criada primeira, foi a aleatoriedade do acesso ao processador que fez com que isso fosse possível, mas isso não impede que a thread que foi criada primeiro não finalize antes da outra.