2016-01-20 64 views
0

我寫了下面程序來測試一些假設我對並行線程:Ç通過共享變量成並行線程

#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

+0

1)不使用參數'argc'。編譯器會發出警告。 2)不使用參數'argv []'。編譯器會發出警告。建議函數'main()'簽名改爲:'int main(void)'。編譯時,始終啓用所有警告,然後修復這些警告。 (對於gcc,至少使用:'-Wall -Wextra -pedantic'(我也使用:'-Wconversion -std = c99') – user3629249

+0

在C中調用'malloc()':1)時,不要強制返回值。它的類型是'void *',可以分配給任何指針。投碼只是使代碼混亂,使其更難以理解,調試和維護。 2)總是檢查(!= NULL)返回的值以確保操作成功。 3)在退出程序之前,將返回的值傳遞給'free()'。在這個簡單的程序中,它不會因爲操作系統的清理而有所作爲,但是在很多程序中,當代碼本身沒有完成清理時,會發生內存泄漏。 – user3629249

回答

2

你已經是共享兩個線程之間的變量 - 它只是你不是指共享副本中main。要引用共享副本,main需要使用args->pingBool

但是,您的代碼將不正確,因爲它會產生數據競爭 - 兩個線程不允許在不使用同步功能的情況下訪問共享變量。改變args->pingBool

ThreadArgs args = (ThreadArgs)malloc(sizeof(struct threadArgs)); 
pthread_mutex_init(&args->lock, NULL); 

main應該鎖定互斥:爲了解決這個問題,你可以使用一個互斥體:

struct threadArgs { 
    pthread_mutex_t lock; 
    int 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); 
+0

謝謝!我不敢相信我沒有意識到我應該在主要中使用'args-> pingBool'。當然,我應該使用互斥體。 – Sam

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; 
} 
-1

嘗試按參考pthread_create()傳遞參數。它看起來像:

pthread_create(&t1, NULL, foo, &args);