How do I know if my threads are actually running at the same time?

Asked

Viewed 94 times

-1

The doubt arose in a college job where we need to make use of threads in . We have been asked to study the "libpthread" so we can get on with the job. The material I’m finding in my research does not answer my doubts and the official documentation I found somewhat confusing. Consider the following code:


/*
    Nesse código bobo, 4 threads são encarregadas de printar sua parte correspondente do vetor, é 
    um vetor de 20 elementos e cada thread está responsável por 5 deles
*/
#include 
#include 
#include 
#include 

typedef struct _lista_numeros {
    int *ponteiro_Lista;
    int parametro;
} lista_numeros;

void imprime_lista (lista_numeros *lista, int inicio, int fim)
{
    int i;
    for (i=inicio; iponteiro_Lista[i]);
    
    printf("\n");
}

void * rotina_de_impressao (void *parametro)
{
    //Pegando o parametro void que chegou e convertendo para t_lista
    lista_numeros *nova_lista = (lista_numeros *) parametro;

    switch (nova_lista->parametro)
    {
        case 1: printf("Thread 1 executando...\n"); imprime_lista(nova_lista, 0, 5); break;
        case 2: sleep(20); printf("Thread 2 executando...\n"); imprime_lista(nova_lista, 5, 10); break;
        case 3: printf("Thread 3 executando...\n"); imprime_lista(nova_lista, 10, 15); break;
        case 4: printf("Thread 4 executando...\n"); imprime_lista(nova_lista, 15, 20); break;
        default: printf("Nenhuma thread em trabalho!"); break;
    }
}

int main ()
{
    //As tais 4 threads responsáveis pela impressão
    pthread_t tarefas[4];
    
    lista_numeros primeira_lista;

    int lista[20] = {/*Para a thread 1*/60,57,8,77,32, /*Para a thread 2*/98,71,95,2,33, 
                    
                    /*Para a thread 3*/24,68,14,85,36, /*Para a thread 4*/25,88,76,11,34};

    primeira_lista.ponteiro_Lista = lista;
    
    primeira_lista.parametro = 1;
    pthread_create(&tarefas[0], NULL, rotina_de_impressao, (void *) &primeira_lista);
    pthread_join(tarefas[0], NULL);

    primeira_lista.parametro = 2;
    pthread_create(&tarefas[1], NULL, rotina_de_impressao, (void *) &primeira_lista);
    pthread_join(tarefas[1], NULL);

    primeira_lista.parametro = 3;
    pthread_create(&tarefas[2], NULL, rotina_de_impressao, (void *) &primeira_lista);
    pthread_join(tarefas[2], NULL);

    primeira_lista.parametro = 4;
    pthread_create(&tarefas[3], NULL, rotina_de_impressao, (void *) &primeira_lista);
    pthread_join(tarefas[3], NULL);
   
    return 0;
}

Note that in the function "routine_de_impressao", if the value of the parameter is 2, I place a Sleep from 20 to delay thread 2, just to check if threads 3 and 4 would be executed, because that’s what I expected, since the idea of threads is to execute code snippets at the same time, right, but what happened is that the output was the same as not having Sleep there, he first waited for Sleep and then ran threads 3 and 4. I didn’t use loop for in creating threads just for didactics. I tried to take off pthread_join to see if the threads actually ran at the same time, but what happened was a completely uneven execution flow.

Exit with sleep() and without sleep() was the same, follows below:


Thread 1 executando...
[60] [57] [8] [77] [32]
Thread 2 executando...
[98] [71] [95] [2] [33]
Thread 3 executando...
[24] [68] [14] [85] [36]
Thread 4 executando...
[25] [88] [76] [11] [34]

How do I actually execute two snippets of code at the same time?

1 answer

0

The problem with your code is that you are starting a thread and then JoinI walk it. You have four boomerangs and you want to launch them at the same time. You 1) throw the first boomerang, wait for it to come back and position itself to hold it; throw the second, wait for it to come back and position itself to hold it; ...; or 2) throw the four Boomerangs at the same time and position itself to hold them as they arrive?

In this analogy, the thread is the boomerang, launch it is the pthread_create and position itself to hold it is the pthread_join. That said, you can refactor your code to

primeira_lista.parametro = 1;
pthread_create(&tarefas[0], NULL, rotina_de_impressao, (void *) &primeira_lista);

primeira_lista.parametro = 2;
pthread_create(&tarefas[1], NULL, rotina_de_impressao, (void *) &primeira_lista);

primeira_lista.parametro = 3;
pthread_create(&tarefas[2], NULL, rotina_de_impressao, (void *) &primeira_lista);

primeira_lista.parametro = 4;
pthread_create(&tarefas[3], NULL, rotina_de_impressao, (void *) &primeira_lista);

pthread_join(tarefas[0], NULL);
pthread_join(tarefas[1], NULL);
pthread_join(tarefas[2], NULL);
pthread_join(tarefas[3], NULL);

However, there will still be inconsistencies in your code since the variable primeira_lista is being used by the four threads at the same time, there may be synchronization problems. There are ways around this, but more ad hoc is you create five arrays for each thread:

#include <stdio.h>
#include <pthread.h>

void imprime_lista (int numeros[5])
{
    for (int i = 0; i < 5; i++) {
        printf("%d ", numeros[i]);
    }
    printf("\n");
}

void * rotina_de_impressao (void *parametro)
{
    int *nova_lista = (int *) parametro;

    int n = nova_lista[0];
    if (n == 2) sleep(5);

    printf("Thread %d executando...\n", n);
    imprime_lista(nova_lista + 1);
}

int main ()
{
    pthread_t tarefas[4];
    
    int p1[6] = {1, 60, 57, 8, 77, 32};
    int p2[6] = {2, 98, 71, 95, 2, 33};
    int p3[6] = {3, 24, 68, 14, 85, 36};
    int p4[6] = {4, 25, 88, 76, 11, 34};

    pthread_create(&tarefas[0], NULL, rotina_de_impressao, (void *) &p1);
    pthread_create(&tarefas[1], NULL, rotina_de_impressao, (void *) &p2);
    pthread_create(&tarefas[2], NULL, rotina_de_impressao, (void *) &p3);
    pthread_create(&tarefas[3], NULL, rotina_de_impressao, (void *) &p4);

    pthread_join(tarefas[0], NULL);
    pthread_join(tarefas[1], NULL);
    pthread_join(tarefas[2], NULL);
    pthread_join(tarefas[3], NULL);
   
    return 0;
}
  • Thank you so much for your help, Enzo! The work I’m doing has a priority queue, where I need to treat the first 5 elements at the same time, so the use of threads. Only in this case it’s just a queue, the idea was that all threads work on the same list, in which case, I kind of should create other printing routines to avoid timing issues? I did that for this silly problem and it worked, but the code gets very polluted with a routine for each thread :|

Browser other questions tagged

You are not signed in. Login or sign up in order to post.