Passing Argument to Threads

Introduction

thread creation 中我們提到 thread 的 start function 只能接收 pointer 作為參數,型別為

(void *)arg

Example

Passing an int

int i = 42
pthread_create(..., my_func, (void *)&i);

Retrieving an int

void *myfunc(void *vptr) {
	int value = *((int *)vptr);
}

Problem

Statement

傳送指標的困難點就是我們必須保證這個指標所指向的記憶體在新的 thread 需要用到此參數的期間都必須是 valid 的

像是如果這個 argument 是 local variable,那麼當函數結束後 local variable 就會變成無效,此可能造成新 thread 在存取時問題

抑或是如果我們不小心改變了該記憶體的值,可能造成新 thread 存取到錯誤的值

Example

void *PrintNo (void *vptr)
{
    printf("My number is %d\n", *((int *) vptr));
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[]) {
    pthread_t tid[10];
    int no;
    
    for( no=0; no<10; no++)
        pthread_create(&tid[no], NULL, PrintNo, (void *) &no);
    
    pthread_exit(NULL);
}
  • 上面的程式碼在 for loop 中 no 會不斷被更改,而 thread 間誰先執行誰後執行取決於 CPU scheduling
  • 所以每個 PrintNo 存取到的 no 可能和預期的不同

Lazy Solution

void *PrintNo (void *vptr)
{
    printf("My number is %d\n", (int) vptr); 
    pthread_exit(NULL);
}
 
int main() {
    pthread_t tid;
    int arg = 42;
    
    // 將 int 變數 arg 的值 (42) 強制轉型為 void *
    // 並作為參數傳遞給 PrintNo
    pthread_create(&tid, NULL, PrintNo, (void *) arg);
    
    pthread_exit(NULL);
}
  • 我們直接將我要要傳的值(42)作為指標傳給 start function
  • 然後 start function 再將這個記憶體位置強制轉成 int
  • 這樣我們達成了類似傳值的效果

這個方法只在 sizeof( int ) <= sizeof( void * ) 下有效