pthread_join () и замороженное выполнение - PullRequest
1 голос
/ 02 марта 2012

Я пытался построить систему (в Linux) с имитацией выполнения времени, координируя потоки с семафорами, идея состояла в том, чтобы сделать их все рабочие циклы за одну секунду, чтобы иметь точное моделирование, которое потоки должны ждать друг друга поток, чтобы закончить его выполнение, на текущей моделируемой секунде.

У меня была действительно досадная утечка памяти, потому что основной поток завершил работу, не присоединяясь к другим потокам (ошибка новичка), поэтому для ее решения я добавил инструкции pthread_join () для каждого потока, предполагая, что они заканчивают свою работу, так как каждое выполнение потока было внутри цикла while с глобальным условием проверки, которое было изменено основным потоком перед завершением. К сожалению, даже при том, что теперь большинство выполнений программы зависает в ожидании завершения потока.

Мне нужно найти способ завершить выполнение каждого потока, даже игнорируя его полную работу, но убедившись, что соединение выполнено (и, таким образом, память освобождена).

Теперь я публикую скомпилированный код с ошибкой, вы можете скомпилировать его с помощью gcc -o sample -pthread sample.c -lm

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include <math.h>

#define SIZE 100
#define READY 12345
#define END 99
#define TIME 3600
int *advicer;
int  *td;
pthread_t *phones;
sem_t *counter;
int ready;
int end;

void cycle(int cycles){
    int i,j,k;
    for(i = 0; i < cycles; i++){
        k = 1;
        while(k){
            k = 0;
            for(j = 0; j < SIZE; j++){
                if(advicer[j] == 0){
                    k = 1;
                    break;
                }
            }
        }
        for(j = 0; j < SIZE; j++){
            advicer[j] = 0;
            sem_post(&counter[j]);
        }
    }
}

void *do_something(void *td){   
    int t;
    t = *((int *) td);
    while(end != END){
        if(end == END)
            break;
        t += t;
        advicer[t] = 1;
        sem_wait(&counter[t]);      
    }
    pthread_exit(NULL);
}

void all_free(){
    int i,j;
    end = END;
    printf("reach %d\n",end);
    for(i = 0; i < SIZE; i++)
        sem_post(&counter[i]);
    printf("reach2\n");
    for(i = 0; i < SIZE; i++){
        pthread_join(phones[i],NULL);
    }
    free(phones);   
    printf("reach3\n");
    for(i = 0; i < SIZE; i++)
        sem_destroy(&counter[i]);
    free(counter);
    free(td);
    free(advicer);
}

void main(){
    int i,my_count;
    counter = (sem_t *)malloc(sizeof(sem_t)*SIZE);
    advicer = (int *)malloc(sizeof(int)*SIZE);
    td = (int *)malloc(sizeof(int)*SIZE);
    phones = (pthread_t *)malloc(sizeof(pthread_t)*SIZE);
    for(i = 0; i < SIZE; i++){
        sem_init(&counter[i], 0, 0);
        advicer[i] = 0;
    }
    ready = READY;
    my_count = 0;
    end = 0;
    for(i = 0; i < SIZE; i++){
        td[i] = i;
        pthread_create(&(phones[i]), NULL, do_something, (void *)(&td[i]));
    }   
    printf("starting simulation\n");
    while(my_count < TIME){
        cycle(60);
        printf("hello\n");
        my_count += 60;
    }
    printf("simulation ended\n");
    all_free();
}

1 Ответ

2 голосов
/ 03 марта 2012

Следующий раздел может привести к блокировке:

for(i = 0; i < m->pp; i++)
  sem_post(&counter[i]);
for(i = 0; i < m->pp; i++){
 if(m->ppl[i] != NULL){
  phone_free(m->ppl[i]);
 }
 ...
}

Вы вызываете sem_post() только для одного потока (который разблокирует его), затем вызываете pthread_join() (через phone_free()) для всех потоков, которые блокируют все, кроме того, для которого вы вызвали sem_post(), как другие не прекращайте, потому что застряли в sem_wait().

Хотя вы и вызывали sem_post() во время основного выполнения (cycle()), поток мог получить значение до вашего вызова кода завершения выполнения (map_free()) pthread_join() (через phone_free()) .

Чтобы отменить тему, вы можете использовать pthread_cancel().

Чтобы избежать утечки памяти, когда вы оставили поток и не вызвали pthread_join(), вы можете отсоединить поток, используя pthread_detach(). Затем ОС освобождает все ресурсы потока, когда поток завершается.

...