用pthreads杀死线程 - C
问题描述:
我有一个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);
}
答
pthread_cancel
气馁,由while(!killed[index]){
更换while(1){
这样做的,而不是正确的方法。然后,杀死你设置的线索killed[index]
。如果您有C11编译器,请使用http://en.cppreference.com/w/c/atomic/atomic_flag,否则您可能需要pthread_mutex
来保护killed
阵列。
例如:https://gustedt.wordpress.com/2012/01/22/simple-c11-atomics-atomic_flag/
首先,这是一个坏主意。其次,'update()'中的'while'循环不包含指定为用于通过'pthread_cancel()'延迟取消的取消点的函数。您可以决定启用异步canellation,但理智的(r)解决方案是在'pthread_mutex_unlock()'之后添加'pthread_testcancel()'。 – EOF
只需添加,在这种情况下异步取消绝对是一个坏主意,因为'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