2011-05-08 54 views
4

我在這段代碼中使用了線程。但是當我在shell中執行此代碼時,某些線程不打印此行。如何同步線程?

printf("\ti'm %dth thread:)", j); 
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file); 

此外,甚至一些線程打印此行兩次。這個過程發生了什麼?以及如何重新組織此代碼,以便線程完全打印一行?

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 
#include <pthread.h> 
#include <errno.h> 

typedef struct {char op; int byte; int seq; int no_file; } ARRAY; 

ARRAY *arr; 

void *thread_operation(void *arg){ 
    int j =*((int*)arg); 
    seq = arr[j].seq; 
    int no_file = arr[j].no_file; 
    printf("\ti'm %dth thread:)", j); 
    printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file); 
} 

int main() 
{ 
    int err, j, i = 10; 
    long int tid; 
    arr = (ARRAY*)malloc(sizeof(ARRAY) * i); 
    srand(time(NULL)); 
    for (i = 0; i <= 10; i++){ 
     arr[i].op = 'r'; 
     arr[i].byte = (rand() % 10); 
     arr[i].seq = i; 
     arr[i].no_file = i + 10; 
} 

    for(j = 0; j < 10; j++){ 
     printf("creating %dth thread.....", j); 
     err = pthread_create(&tid, NULL, thread_operation, &j); 
     if(err != 0) 
     printf("%s\n", strerror(err)); 
     printf("%dth done\n", j); 
    } 

    return 0; 
} 

這是結果從我的電腦

creating 0th thread.....0th done 
creating 1th thread..... i'm 0th thread:) r 9 0 10 
1th done 
creating 2th thread..... i'm 2th thread:) r 3 2 12 
    i'm 2th thread:) r 3 2 12 
2th done 
creating 3th thread..... i'm 3th thread:) r 6 3 13 
3th done 
creating 4th thread..... i'm 4th thread:) r 9 4 14 
4th done 
creating 5th thread..... i'm 5th thread:) r 3 5 15 
5th done 
creating 6th thread..... i'm 6th thread:) r 2 6 16 
6th done 
creating 7th thread..... i'm 7th thread:) r 2 7 17 
7th done 
creating 8th thread.....8th done 
creating 9th thread..... i'm 8th thread:) r 6 8 18 
9th done 
    i'm 9th thread:) r 8 9 19 
    i'm 9th thread:) r 8 9 19 

回答

6

您需要使用互斥噸避免競爭狀態,而且你還需要使用pthread_join完成所有線程的進程死掉之前同步。

互斥允許你停止某些線程,而其中之一是使用共享的ressource執行動作(見男人的pthread_mutex_lock,調用pthread_mutex_init)

在pthread_join是在代碼中必不可少的,因爲它迫使你的主線程等待你創建的其他線程,如果你不使用它,你不能確定當主線程從主線程返回時所有的線程都會完成。

+1

謝謝..爲什麼一些線程(在上例中,第9個線程)執行了兩次? – manut 2011-05-08 11:30:31

+0

比賽條件可能會導致未定義的行爲,請考慮驗證我的答案:) – Intrepidd 2011-05-08 17:49:11

1

使用printf與線程之間的不完整行通常不會工作。您可能會完全損壞輸出。另外,屏幕上顯示的行的順序通常不是執行順序,而是線程訪問共享資源stdout的順序。

2

有些人打印出來的原因是兩次(比如線程編號9),因爲你正在傳遞一個指向你的循環變量的指針作爲thread_operation的輸入。

for(j = 0; j < 10; j++){ 
    err = pthread_create(&tid, NULL, thread_operation, &j);<---here 

是& j被最終被thread_operation間接引用:

void *thread_operation(void *arg){ 
    int j =*((int*)arg);<---here 

,但在這一點上環可能擁有先進和j的值(在線程中運行)將是什麼Ĵ恰好是現在在循環中。解決這個問題的方法是不傳遞指針,而是將j的值傳遞給線程構造函數。改變你在pthread_create傳遞值:

pthread_create(&tid, NULL, thread_operation, (void*) j); 

,並在你的線程投值出線的說法:

int j =(int)arg; 

現在從技術上來說這依賴於一個事實,即intvoid*大小相同當他們通常不是。但是,只要你不使用巨大的值,這將工作。

對於所有其他問題@Intrepidd是正確的關於使用pthread_join來確保在所有線程完成之前該進程不會退出。

+0

+1關於指針:) – Intrepidd 2011-05-08 17:52:45