2016-04-14 190 views
3

我有一個C pthread程序,它在main中創建N個線程來更新一個全局變量。 Main也在所有這些更新線程上調用pthread_join來等待它們完成。我還有2個使用pthread條件變量的觀察者線程來檢查全局變量是高於還是低於特定數字,如果是,它將殺死所有更新線程和另一個觀察者線程。但是,我遇到了這最後一部分的麻煩..殺死其他線程。我的程序做它應該做的事,但從來沒有完成...它只是被卡住了。在每個觀察者線程結束時調用exit(0),但我覺得這太懶惰的解決方案,我真的想學習如何從一個單獨的線程中殺死其他線程並返回到main。用pthreads殺死線程 - C

這裏是我的代碼:

#include <pthread.h> 
#include <time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

void *update(void *i); 
void *watchIncrease(); 
void *watchDecrease(); 

//init globals 
double marketValue; 
int numThreads; 
double *stocks; 
double ceiling; 
double floor_; 
int flag; 

pthread_t *threads; 
pthread_t watchIncreaseThread; 
pthread_t watchDecreaseThread; 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t threshold_ceiling; 
pthread_cond_t threshold_floor_; 

int main(int argc, char **argv){ 

    numThreads = atoi(argv[1]); 
    int level = atoi(argv[2]); 

    marketValue = 100 * numThreads; 
    //initialize personal stocks for threads 
    stocks = (double *) malloc(sizeof(double) * numThreads); 
    int i; 
    for(i = 0; i < numThreads; i++) stocks[i] = 100; 
    //initialize floor/ceiling 
    double percent = (double) level/100; 

    double cap = marketValue * percent; 
    ceiling = marketValue + cap; 
    floor_ = marketValue - cap; 

    //seed rand() 
    srand(time(NULL)); 
    //create threads 
    pthread_cond_init(&threshold_ceiling,NULL); 
    pthread_cond_init(&threshold_floor_,NULL); 

    int rc = pthread_create(&watchIncreaseThread,NULL,watchIncrease,NULL); 
    assert(rc == 0); 
    rc = pthread_create(&watchDecreaseThread,NULL,watchDecrease,NULL); 
    assert(rc == 0); 

    threads = (pthread_t *)malloc(sizeof(pthread_t) * numThreads); 
    assert(threads != NULL); 
    for(i = 0; i < numThreads; i++){ 
     int rc = pthread_create(&threads[i],NULL,update,(void *)i); 
     assert(rc == 0); 
    } 

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

    return 0; 
} 

void *update(void *i){ 

    int index = (int)i; 
    double max = 2; 
    double val; 

    while(1){ 
     int rc = pthread_mutex_lock (&lock); 
     assert(rc == 0); 
     val = max * ((double)rand()/(double)RAND_MAX - 0.5); 
     stocks[index] += val; 

     marketValue += val; 
     pthread_cond_signal (&threshold_ceiling); 
     pthread_cond_signal (&threshold_floor_); 
     pthread_mutex_unlock(&lock); 

    } 

} 

void *watchIncrease(){ 

    int rc = pthread_mutex_lock(&lock); 
    assert(rc == 0); 
    while(marketValue < ceiling){ 
     pthread_cond_wait(&threshold_ceiling, &lock); 
    } 
    printf("Market Up to %.2f\n",marketValue); 
    int i; 
    double sum = 0; 
    for(i = 0; i < numThreads; i++){ 
     sum += stocks[i]; 
    } 
    printf("Total Market Price of %d stocks: %.2f\n",numThreads,sum); 
    for(i = 0; i < numThreads; i++){ 
     rc = pthread_cancel(threads[i]); 
     assert(rc == 0); 
    } 
    pthread_cancel(watchDecreaseThread); 
    pthread_mutex_unlock(&lock); 
    pthread_exit(NULL); 

    //exit(0); 
} 

void *watchDecrease(){ 

    int rc = pthread_mutex_lock(&lock); 
    assert(rc == 0); 
    while(marketValue > floor_){ 
     pthread_cond_wait(&threshold_floor_, &lock); 
    } 
    printf("Market Down to %.2f\n",marketValue); 
    int i; 
    double sum = 0; 
    for(i = 0; i < numThreads; i++){ 
     sum += stocks[i]; 
    } 
    printf("Total Market Price of %d stocks: %.2f\n",numThreads,sum); 
    for(i = 0; i < numThreads; i++){ 
     rc = pthread_cancel(threads[i]); 
     assert(rc == 0); 
    } 
    pthread_cancel(watchIncreaseThread); 
    pthread_mutex_unlock(&lock); 
    pthread_exit(NULL); 
    //exit(0); 


} 
+1

首先,這是一個壞主意。其次,'update()'中的'while'循環不包含指定爲用於通過'pthread_cancel()'延遲取消的取消點的函數。您可以決定啓用異步canellation,但理智的(r)解決方案是在'pthread_mutex_unlock()'之後添加'pthread_testcancel()'。 – EOF

+0

只需添加,在這種情況下異步取消絕對是一個壞主意,因爲'pthread_mutex_lock()','pthread_mutex_unlock()'或'pthread_cond_signal()'都是異步取消安全的(https://www.gnu.org /software/libc/manual/html_node/POSIX-Safety-Concepts.html)。如上所述,在while循環的開始或結尾處(互斥鎖未鎖定的地方)的'pthread_testcancel()'是最好的選擇。 – sonicwave

回答