2016-04-14 12 views
3

Ich habe ein C Pthread-Programm, das N Threads in Haupt erstellt, die eine globale Variable aktualisieren. Main ruft pthread_join in all diesen Update-Threads auf, um darauf zu warten, dass sie beendet werden. Ich habe auch 2 Watcher-Threads, die pthread-Bedingungsvariablen verwenden, um zu überprüfen, ob die globale Variable über oder unter bestimmten Zahlen liegt, und wenn dies der Fall ist, werden alle Update-Threads und der andere Watcher-Thread beendet. Allerdings habe ich Probleme mit diesem letzten Teil ... die anderen Threads zu töten. Mein Programm macht, was es tun soll, aber nie beendet ... es bleibt einfach stecken. Der Aufruf von exit (0) am Ende jedes Watcher-Threads funktioniert zwar, aber ich denke, das ist zu faul für eine Lösung. Ich würde gerne lernen, wie man andere Threads aus einem separaten Thread killt und zum main zurückkehrt.Killing Threads mit Pthreads - C

Hier ist mein Code:

#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

Zunächst ist dies eine schlechte Idee. Zweitens enthält die 'while'-Schleife in' update() 'keine Funktionen, die als" cancellation-points "für die verzögerte Löschung durch" pthread_cancel() "spezifiziert sind. Sie könnten asynchrone Canellation aktivieren, aber die vernünftige (r) Lösung wäre es, nach dem 'pthread_mutex_unlock()' 'pthread_testcancel()' hinzuzufügen. – EOF

+0

Nur um hinzuzufügen, asynchrone Löschung ist in diesem Fall definitiv eine schlechte Idee, da weder 'pthread_mutex_lock()', 'pthread_mutex_unlock()' oder 'pthread_cond_signal()' async-cancel-sicher sind (https://www.gnu.org /software/libc/manual/html_node/POSIX-Safety-Concepts.html). Wie gesagt, ein 'pthread_testcancel()' am Anfang oder Ende der 'while'-Schleife (wo der Mutex nicht gesperrt ist) wäre der bessere Weg. – sonicwave

Antwort