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);