C 将共享变量传递给 pthread
C passing shared variables into pthreads
我编写了以下程序来测试我对 pthread 的一些假设:
#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;
}
基本上,它在 main()
中设置一个变量 int pingBool = 1
,将其传递到一个循环直到 pingBool == 0
的线程中。 main()
然后设置 pingBool = 0
,但是,线程继续到 运行。我很确定这种情况正在发生,因为 pingBool
在被放入结构中时被复制,并且只有 main()
的本地副本被修改。
有没有办法像这样在线程之间共享和修改变量?我知道我可以简单地使 pingBool
成为一个全局变量而不是将它传递给 foo()
。但是,我不想那样做。
注意:如果您想测试代码,您需要根据您的编译器使用 -pthread 或 -lpthread 进行编译。即 gcc -Wall -Werror -pthread -o test test.c
没关系,自己解决了。诀窍是传递一个指向原始变量的指针,并从 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;
}
尝试通过引用 pthread_create()
传递参数。它看起来像:
pthread_create(&t1, NULL, foo, &args);
您已经在两个线程之间共享变量 - 只是您没有引用 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);
我编写了以下程序来测试我对 pthread 的一些假设:
#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;
}
基本上,它在 main()
中设置一个变量 int pingBool = 1
,将其传递到一个循环直到 pingBool == 0
的线程中。 main()
然后设置 pingBool = 0
,但是,线程继续到 运行。我很确定这种情况正在发生,因为 pingBool
在被放入结构中时被复制,并且只有 main()
的本地副本被修改。
有没有办法像这样在线程之间共享和修改变量?我知道我可以简单地使 pingBool
成为一个全局变量而不是将它传递给 foo()
。但是,我不想那样做。
注意:如果您想测试代码,您需要根据您的编译器使用 -pthread 或 -lpthread 进行编译。即 gcc -Wall -Werror -pthread -o test test.c
没关系,自己解决了。诀窍是传递一个指向原始变量的指针,并从 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;
}
尝试通过引用 pthread_create()
传递参数。它看起来像:
pthread_create(&t1, NULL, foo, &args);
您已经在两个线程之间共享变量 - 只是您没有引用 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);