2017-03-06 99 views
1

我在C中使用posix線程。我的程序中有兩個線程,即thread1和thread2。 thread1啓動thread2。基於來自調用線程的變量值關閉線程

thread1維護變量var1,基於哪個thread2必須安全退出。

thread2調用很多冗長的函數(其運行時間可能高達5秒)。在thread2中有很多使用malloc的內存分配。只要var1成爲真,我需要關閉thread2,但是隻有在釋放所有分配的內存之後。如何做到這一點?

的代碼看起來是這樣的:

void * func1(void *arg) 
{ 
    pthread_create(&thread2, &attr, func2, NULL); 
    while(1) 
    { 
     // ... 
     var1 = func3(); 
     if(var1 == true) 
     { 
      // Cancel thread2 
     } 
     // ... 
    } 
} 

void * func2(void *arg) 
{ 
    // ... 
    func4(); // runs for 2 sec 
    char* var2 = malloc(10); 
    func5(); // runs for 5 sec 
    char* var3 = malloc(20); 
    // ... 
cleanup: 
    free(var2); 
    free(var3); 
    return (void*) 0; 
} 
+0

我的問題是如何安全關閉/退出/取消thread2? – mk09

+2

沒有神奇的捷徑。你必須執行這個過程的每個部分,包括檢查安全點的取消並適當地釋放資源。 –

回答

4

有幾種方法可以實現這一點。這裏有一個:

從thread1的角度來看,您可以簡單地在thread2上使用pthread_cancel。但是你需要重新調整thread2以確保它在安全的地方有取消點。你想也需要調整,你如何把你的數據,以便取消回調被調用線程2:

struct func2_data { 
    char *var2; 
    char *var3; 
}; 

void func2_cleanup(void *vdata) { 
    struct func2_data *data = vdata; 
    free(data->var2); 
    free(data->var3); 
} 

void * func2(void *arg) 
{ 
    struct func2_data data = { 
    NULL, NULL 
    }; 

    pthread_cleanup_push(func2_cleanup, &data); 

    // ....  

    func4(); 
    data.var2 = malloc(10); 
    pthread_testcancel(); 

    func5(); 
    data.var3 = malloc(10); 
    pthread_testcancel(); 

    // ....   

    pthread_cleanup_pop(1); 
    return NULL; 
} 

那麼這裏發生了什麼?

  1. 所有需要釋放的指針都捆綁在一起並初始化爲NULL。如果在任何單個變量被分配之前調用清理函數,則允許對free的調用將它們視爲無操作。

  2. 註冊回調以釋放指針。該回調將在任何取消點被調用。包括線程從其處理函數返回的時間。所以除了調用pop之外,你不需要明確地關心它。

  3. 取消積分在pthread_testcancel的基礎上添加,在各種「安全」的地方。從而允許線程在計算之間過早結束。如果您認爲合適,請添加它們。

+0

你能告訴我更多關於pthread_testcancel的信息嗎?請問pthread_cancel是否等待thread2到達pthread_testcancel調用取消? – mk09

+0

@ mk09 - 默認行爲是'pthread_testcancel'只是檢查是否有取消請求,而'pthread_cancel'只是將請求添加到隊列中。兩個線程都不會等待其他線程。 – StoryTeller

+0

在調用pthread_cancel或線程2到達pthread_testcancel調用之後,線程2是否立即取消? – mk09

1

即使你在沒有理解正確的問題,在下面的代碼我給一個想法來處理事情。使用ptread_join可安全退出線程

void * func1(void *arg) 
{ 
    pthread_create(&thread2, &attr, func2, (void*)&var1); /* Pass addr of var1 as argument to thread*/ 
    while(1) 
    { 
     ... 
     var1 = func3(); 
     if(var1 == TRUE){ 
      int *ret; 
      pthread_join(thread2,&ret); 
     } 
     ... 
    } 
} 

void * func2(void *arg) 
{ 
    bool *check = (bool*)arg; 
    ... 
    func4(); // runs for 2 sec 
    if(*check == TRUE) 
     goto end; 
    char* var2 = malloc(10); 
    func5(); // runs for 5 sec 
    if(*check == TRUE) 
     goto clean_var2; 
    char* var3 = malloc(20); 
    ... 
    cleanup: 
    free(var3); 
    clean_var2: 
    free(var2); 
    end: 
    return (void*) 0; 
}