2012-03-02 77 views
1

我試圖建立一個系統(在Linux中)模擬時間執行,用信號協調線程,這個想法是讓他們所有的工作週期爲一秒鐘,以便有一個精確的模擬線程必須等待每個其他線程結束其執行,在當前的模擬秒。pthread_join()和凍結執行

因爲主線程完成了工作而沒有加入其他線程(新手錯誤),所以爲了解決這個問題,我爲每個線程添加了pthread_join()指令,假設他們正在完成工作,因爲每個線程的執行都在一個while循環中,並且要檢查全局條件,在完成之前主線程已經修改了這個條件。令人難過的是,現在,大部分程序的執行都被凍結,等待線程完成。

我需要找到一種方法來結束每個線程的執行,甚至忽略它的全部工作,但要確保連接已經完成(並且釋放內存)。

現在我用後該錯誤的編譯代碼,你可以用gcc編譯-o樣-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(); 
} 
+2

代碼(接近您的實際代碼)比描述更好地溝通代碼所做的事情。小細節在線程中很重要。 – 2012-03-02 19:40:58

+0

'我有一個非常惱人的內存泄漏' - 你怎麼知道的,以及你在運行什麼操作系統?對於大多數OS/crt,退出主線程會導致進程終止,因此會終止所有線程並釋放所有內存。 – 2012-03-02 19:47:35

+0

@MartinJames因爲我使用valgrind查找內存泄漏,並且我發現了一些posix線程的文檔,說如果我不做任何連接預計會發生,因爲 默認情況下pthreads是可連接的,所以他們需要加入一個好的自由。順便說一下操作系統是Linux。 – Mig 2012-03-02 20:40:12

回答

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()

雖然主執行( cycle())的值可能已經呼叫到最終執行代碼( map_free()pthread_join()(通過 phone_free())之前獲取的線程中調用 sem_post()

要取消某個線程,您可以使用pthread_cancel()

爲了避免當具有左螺紋,而不是要求它pthread_join()的內存泄漏,您可以使用pthread_detach()分離線程。當線程終止時,OS釋放所有線程的資源。

+0

你已經被格式化不好的代碼上當 - 沒有一組嵌套循環。該'sem_post()'調用是第一個'for'迴路中的唯一聲明,因此所有的信號燈上移動到「連接」循環前「發佈」。 – 2012-03-03 23:57:04

+0

@Michael Burr:Dxmn ... - 你是對的。無論如何,這個結構引入了一個可能導致鎖定的競爭條件。我會糾正我的答案。謝謝。 – alk 2012-03-04 07:45:22

+0

我認爲更新不正確。任何在'sem_post()'調用之後醒來的線程都會看到'end == END'並且將退出while循環。線程必須重新讀取'end'變量,因爲'sem_wait()'是內存屏障,'end'是全局變量。即使工作線程在主線程到達相應的'pthread_join()'之前退出,連接也會成功完成。 – 2012-03-04 08:06:58