我编写了以下程序来测试我对pthreads的一些假设:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef struct threadArgs * ThreadArgs;
void *foo( void * argStruct );
struct threadArgs{
int pingBool;
};
int main(int argc, char const *argv[]){
pthread_t t1;
int pingBool = 1;
int ch;
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
args->pingBool = pingBool;
pthread_create(&t1, NULL, foo, args);
while((ch = getchar()) != EOF ){
if( ch == 'q' ){
pingBool = 0;
printf("pingBool now 0\n");
break;
}
}
pthread_join(t1, NULL);
printf("whole program terminating\n");
return 0;
}
void *foo( void * argStruct ){
ThreadArgs args = argStruct;
while( args->pingBool == 1 ){
printf("t1 still going\n");
sleep(1);
}
printf("t1 finished\n");
return NULL;
}
基本上,它在int pingBool = 1
中设置变量main()
,将其传递给循环直到pingBool == 0
的线程。 main()
然后设置pingBool = 0
,但线程继续运行。我很确定这种情况正在发生,因为pingBool
在被放入结构时被复制,只有main()
的本地副本被修改。
有没有办法在这样的线程之间共享和修改变量?我知道我可以简单地将pingBool
设为全局变量,而不是将其传递给foo()
。但是,我宁愿不这样做。
注意:如果要测试代码,则需要使用-pthread或-lpthread进行编译,具体取决于您的编译器。即gcc -Wall -Werror -pthread -o test test.c
答案 0 :(得分:2)
您已经在两个线程之间共享变量 - 它只是您没有引用main
中的共享副本。要引用共享副本,main
需要使用args->pingBool
。
然而,您的代码将不正确,因为它将具有数据争用 - 不允许两个线程在不使用同步功能的情况下访问共享变量。要解决此问题,您可以使用互斥锁:
struct threadArgs {
pthread_mutex_t lock;
int pingBool;
};
需要初始化:
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
pthread_mutex_init(&args->lock, NULL);
更改main
时 args->pingBool
应锁定互斥锁:
if ( ch == 'q' ) {
pthread_mutex_lock(&args->lock);
args->pingBool = 0;
pthread_mutex_unlock(&args->lock);
printf("pingBool now 0\n");
break;
}
并且线程应该在读取时将其锁定:
pthread_mutex_lock(&args->lock);
while ( args->pingBool == 1 ) {
pthread_mutex_unlock(&args->lock);
printf("t1 still going\n");
sleep(1);
pthread_mutex_lock(&args->lock);
}
pthread_mutex_unlock(&args->lock);
答案 1 :(得分:0)
没关系,自己解决了。诀窍是传入一个指向原始变量的指针,并从foo()
访问该指针的值。修改后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef struct threadArgs * ThreadArgs;
void *foo( void * argStruct );
struct threadArgs{
int *pingBool; // Now a pointer, not an int
};
int main(int argc, char const *argv[]){
pthread_t t1;
int pingBool = 1;
int ch;
ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs));
args->pingBool = &pingBool; // pass in a pointer to the variable, rather than the variable itself
pthread_create(&t1, NULL, foo, args);
while((ch = getchar()) != EOF ){
if( ch == 'q' ){
pingBool = 0;
printf("pingBool now 0\n");
break;
}
}
pthread_join(t1, NULL);
printf("whole program terminating\n");
return 0;
}
void *foo( void * argStruct ){
ThreadArgs args = argStruct;
int * pingBool = args->pingBool;
while( *pingBool == 1 ){ // access the value of the pointer
printf("t1 still going\n");
sleep(1);
}
printf("t1 finished\n");
return NULL;
}
答案 2 :(得分:-1)
尝试通过引用传递args pthread_create()
。它看起来像是:
pthread_create(&t1, NULL, foo, &args);