2012-08-11 37 views
1

我是這些pthreads的新手。我寫了一個程序,以便隨機顯示數字,而不是按順序顯示。我已經使用pthrea_join()方法。該程序如下:pthreads不是連續執行的

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
    cnt++; 
    printf("thread no. %d\n",cnt); 
} 
void tosync() 
{ 
    if(i>0) 
    pthread_join(th[i-1],NULL); // <---here i am blocking the previous thread..       
    printmsg(); 
} 
void main(void) 
{ 
    pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
    for(i=1;i<10; i++){ 
    pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
    } 
    int y; 
    for(int i=0; i<10; i++) 
    pthread_join(th[i],NULL); 
    return; 
} 

不過我得到隨機數字...... plzz。幫助

+1

看來你在訪問全局變量'i'時有問題。從主線程(增量)以及工作線程。除此之外,你期望'th [0]'做什麼?等待自己? – Xyand 2012-08-11 18:02:25

+0

對不起,我忘了編輯...即使現在我隨機得到的數字 – nitish712 2012-08-12 07:51:03

回答

1

pthread_join(th [i-1],NULL)這行有一些問題。當你創建一個線程時,你會增加i的值。假設 創建第一個三線程操作系統切換第三線程啓動和操作系統切換到主線程創建其餘線程。在創建完所有線程後,我的值爲10/ 現在假設OS切換到第三線程,然後等待10-1 =第9線程完成並且類似地繼續。因此最終它總是隨機打印。你的策略是錯誤的。

試試這個

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
cnt++; 
printf(thread no. %d\n",cnt); 
} 
void tosync() 
{ 

printmsg(); 
} 
void main(void) 
{ 
pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
for(i=1;i<10; i++){ 
pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
pthread_join(th[i],NULL); // <---here i am blocking the previous thread.. 
} 

return; 
} 
1

toSync功能,您使用的是i值,問題是你不知道的toSync功能運行時,什麼樣的價值i了。

在極端情況下,它可能對所有線程的值爲10,如果創建線程的循環在任何創建的線程運行之前就會運行,則會發生此情況。

乾淨的解決方案是將i值作爲參數傳遞給pthread_create,並讓toSync使用該值代替全局i。例如。

int *id = (int*)malloc(sizeof(int)); 
*id = i; 
pthread_create(&th[i],NULL, (void*) &tosync, id); 

其他事情要考慮:

  1. toSync需要特殊處理的線程ID爲0,因爲它沒有任何的前身等待
  2. main最後的循環不應該在線程0-8上調用pthread_join,因爲它們已經加入。在同一個線程調用pthread_join幾次的結果是undefined
+1

使用'malloc'這是內存和CPU時間的主要浪費。只需將'i'轉換爲'void *'而不是取其地址,並在線程啓動函數中將其重新轉換爲int。 – 2012-08-11 18:13:33

+0

@R啊,好點! – johlo 2012-08-11 18:15:17

+0

還要注意,這是浪費同步:在一個線程中調用'malloc',在另一個線程中調用'free'將始終有一些隱藏的同步成本獲取內存並將其返回到空閒池以重用。 – 2012-08-11 18:22:25

1

正在發生的事情是,你tosync()方法使用全局變量i,而不是明知的i值當線程實際上是開始。如果你想通過i(或者這裏指向前一個pthread_t的指針)到tosync,以便它實際上記得它應該加入哪個線程,你需要通過pthread_create來傳遞它,類似於;

void* tosync(void* ptr) 
{ 
    pthread_t* threadIndex = (pthread_t*)ptr; 
    if(threadIndex != NULL) 
     pthread_join(*threadIndex, NULL); // <---here i am blocking the previous thread..       
    printmsg(); 
} 

...in the loop... 

pthread_create(&th[i], NULL, tosync, &th[i-1]); 

這是最後一個參數給pthread_create將作爲threadIndex在你的方法來傳遞,如果包含索引,每個線程都知道它的單獨的索引。

+0

不錯,你只需要小心第一個線程,所以'pthread_create'調用和'tosync'必須包含一些條件。 – 2012-08-11 21:04:50

+0

@JensGustedt好點。它應該足以檢查NULL並讓第一個線程繼續傳遞NULL作爲參數。修正了代碼:) – 2012-08-11 21:52:55

+0

@Isaksson現在我清楚哪裏出了問題... thanx :) – nitish712 2012-08-12 07:59:16

1

另一種方法:

#include <stdio.h> 
#include <pthread.h> 

struct threadData{ 
    int id; 
    pthread_t prev; 
}; 


void tosync(void *data) 
{ 
    struct threadData *td=data; 
    if ((*td).prev!=0){ 
     printf("%i waiting\n",(*td).id); 
     fflush(0); 
     pthread_join((*td).prev,NULL); // <---here i am blocking the previous thread..       
    } 
    printf("%i runnning\n",(*td).id); 
    fflush(0); 
    free(td); 
} 

int main(void) 
{ 
    int i; 
    struct threadData *td; 
    pthread_t nextThreadID=0; 
    for(i=0;i<10; i++){ 
     td=malloc(sizeof(struct threadData)); 
     (*td).prev=nextThreadID; 
     (*td).id=i; 
     pthread_create(&nextThreadID,NULL, (void*) &tosync, (void *)td); 
    } 
    pthread_join(nextThreadID,NULL); 
    return 0; 
} 
2

你應該通過東西到你的日常tosync讓每個線程都知道它應該等待的線程。另外,第一個線程不應該等待任何人。如果您使用線程啓動例程的正確簽名,則可以傳遞參數。

void * tosync(void *arg) 
{ 
    pthread_t *me = (pthread_t *)arg; 
    if (me > th) pthread_join(me[-1],NULL); 
    printmsg(); 
    return 0; 
} 

main應返回int。現在循環已經簡化了,因爲啓動例程不再需要強制轉換。由於每個線程都已加入其前任,因此main線程只需要連接最後一個線程。

int main(void) 
{ 
    for(i=0;i<10; i++){ 
    pthread_create(&th[i],NULL, tosync, &th[i]); 
    } 
    pthread_join(th[9],NULL); 
    return 0; 
}