2016-04-14 135 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

回答