pthread_join()和冻结执行

时间:2012-03-02 19:35:17

标签: c linux multithreading pthreads semaphore

我正在尝试使用模拟时间执行来构建一个系统(在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 个答案:

答案 0 :(得分:2)

以下部分可能导致锁定:

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() 1}} for,因为其他人没有终止,因为卡在sem_post()

虽然在主执行期间(cycle())调用了map_free(),但在调用结束执行代码之前,线程可能已经获取了该值({{ 1}})pthread_join()(通过phone_free())。

要取消线程,您可以使用pthread_cancel()

为了避免在离开线程而不在其上调用pthread_join()时发生内存泄漏,您可以使用pthread_detach()分离线程。然后,当线程终止时,操作系统将释放所有线程的资源。