Проблема синхронизации с pthreads с помощью pthread_join - PullRequest
1 голос
/ 21 марта 2019

У меня есть следующие циклы,

for (i = 1; i < nDiag; ++i)
{
    elem = findelemnum();
    taskarr[3]= elem;
    if(threadnum > elem) limit = elem;
    else limit=threadnum;

    if (i <= lenA) 
    {
        si = i;
        sj = 1;
    } 
    else 
    {
        si = lenA;
        sj = i - lenA + 1;
    }
    taskarr[0] = si, taskarr[1] = sj;  

    for (j = 0; j < limit; ++j) 
    {
        taskarr[2] = j;
        wakeup = 0;
        pthread_create(&threads[j], NULL, mytask, taskarr);
        while(!wakeup){
        }
    }
    for (int j=0; j < limit ;j++){
        pthread_join(threads[j],NULL);  
    } 
}

Я хочу синхронизировать свои потоки, чтобы все потоки сначала завершили внутренний цикл, а затем запустил новый цикл (i ++).По этой причине я использовал функцию pthread_join.Хотя новый цикл for i начинается раньше, чем заканчивается.Что я делаю не так?

1 Ответ

2 голосов
/ 21 марта 2019

Если вы хотите дождаться наступления определенного условия, используйте класс функций pthread_cond_*.

Если вы просто хотите подождать, пока поток выполнит свою работу, удалите while(!wakeup){}.Это работает, потому что

int pthread_join (поток pthread_t, void ** value_ptr);

Функция pthread_join () приостанавливает выполнение вызывающего потока до тех пор, пока целевой поток не завершится, если только целевой объектпоток уже завершен.

Итак, в следующем фрагменте вы сначала создаете limit потоков, и они сразу же начинают работать.Затем вы ждете окончания каждого потока, то есть вы приостанавливаете вызывающий поток до завершения limit потоков.

for (j = 0; j < limit; ++j) 
{
    taskarr[2] = j;
    wakeup = 0;
    pthread_create(&threads[j], NULL, mytask, taskarr);
}

for (int j=0; j < limit ;j++){
    pthread_join(threads[j],NULL);  
} 

Это небольшая демонстрация

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

#define NTHREAD 4
#define ITERATIONS 5

typedef struct _pcontext
{
    int id;
    int iteration;
}pcontext_t;

void* work(void* arg)
{
    pcontext_t* ctx = (pcontext_t*)arg;

    sleep(2); 

    printf("Thread ID: %d\n", ctx->id);
    printf("Iteration nr: %d\n", ctx->iteration);
    printf("Done.\n\n");

    return NULL;
}

int main()
{
    pthread_t thread[NTHREAD];
    pcontext_t ctx[NTHREAD];
    int err;
    int i,j;

    for(j = 0; j < ITERATIONS; j++)
    {
        for(i = 0; i < NTHREAD; i++)
        {
            ctx[i].id = i;
            ctx[i].iteration = j;
            err = pthread_create(&thread[i], NULL, work, (void*)(&(ctx[i])));
            if (err)
            {
                printf("An error occured: %d", err);
                return err;
            }
        }

        printf("Waiting for the threads to end...\n");

        for(i = 0; i < NTHREAD; i++)
        {
          pthread_join(thread[i], (void**)NULL);    
        }

        printf("Threads ended.\n");
        printf("Iteration %d ended.\n\n", j);
    } 

    return 0;
}

Выход:

gcc -Wall -Wextra -pedantic -pthread -o main main.c 
Waiting for the threads to end...
Thread ID: 1
Iteration nr: 0
Done.

Thread ID: 0
Iteration nr: 0
Done.

Thread ID: 2
Iteration nr: 0
Done.

Thread ID: 3
Iteration nr: 0
Done.

Threads ended.
Iteration 0 ended.

Waiting for the threads to end...
Thread ID: 0
Iteration nr: 1
Done.

Thread ID: 3
Iteration nr: 1
Done.

Thread ID: 2
Iteration nr: 1
Done.

Thread ID: 1
Iteration nr: 1
Done.

Threads ended.
Iteration 1 ended.
...