2013-06-26 60 views
5

我想知道如果兩個線程同時調用相同的函數會發生什麼情況,並且函數是通過套接字發送文本的UDP客戶端。如果多個pthread使用相同的函數,會發生什麼

考慮到下面的代碼,我一直在運行它,但我還沒有得到任何錯誤。我不知道它是否會因爲線程同時使用相同的源(函數,變量,IP,端口)而崩潰,以及它們如何共享源?我可以想象下面的代碼是多線程的錯誤用法,你能否解釋一下如何使用這些線程,以便一個線程可以使用該函數,而不是其他線程正在使用該函數?換句話說,它怎麼可能是線程安全的?

爲Linux中的示例C代碼:

void *thread1_fcn(); 
void *thread2_fcn(); 
void msg_send(char *message); 

int main(void){ 
    pthread_t thread1, thread2; 
    pthread_create(&thread1, NULL, thread1_fcn, NULL); 
    pthread_create(&thread2, NULL, thread2_fcn, NULL); 
    while(1){} 
    return 0; 
} 

void *thread1_fcn(){ 
    while(1){ 
     msg_send("hello"); 
     usleep(500); 
    } 
    pthread_exit(NULL); 
} 

void *thread2_fcn(){ 
    while(1){ 
     msg_send("world"); 
     usleep(500); 
    } 
    pthread_exit(NULL); 
} 

void msg_send(char message[]){ 
     struct sockaddr_in si_other; 
     int s=0; 
     char SRV_IP[16] = "192.168.000.002"; 

     s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
     memset((char *) &si_other, 0, sizeof(si_other)); 
     si_other.sin_family = AF_INET; 
     si_other.sin_port = htons(12346); 
     si_other.sin_addr.s_addr = htonl(INADDR_ANY); 
     inet_aton(SRV_IP, &si_other.sin_addr); 
     sendto(s, message, 1000, 0, &si_other, sizeof(si_other)); 
     close(s); 
} 
+2

調用同一個函數沒有問題(每個線程都有自己獨立的執行上下文和堆棧)。有*可能會*訪問共享狀態(包括庫調用中的共享狀態) - 考慮自我分析代碼以查看共享狀態(如果有),並圍繞此問題集中討論問題。 – user2246674

+1

自動變量的美妙之處在於,一切都自動運行。 –

+1

'thread1_fcn()'和'thread12_fcn()'仍應該聲明爲一個'void *'參數來匹配'pthread_create()'的期望值。 – jxh

回答

3

既然你創建和關閉內msg_send插座,沒有什麼特別的會發生。一切都會正常工作。

3

你的代碼沒有任何問題。即使它運行相同的代碼,每個線程都有一個單獨的堆棧,因此它有一組獨立的變量。沒有變量被共享。

1

您的代碼調用未定義的行爲,因爲線程通過小字符串文字作爲message參數,但函數嘗試從message基地址開始發送1000個字節。

由於sendto通常是直接調用操作系統,要麼你會通過UDP發送大量垃圾(或更糟糕的是:安全敏感的信息!),否則系統調用會檢測到超出邊界的內存訪問並返回-1與errno設置爲類似EFAULT(可能沒有發送任何數據)。

由於message是一個字符串,因此您應計算其長度,然後只發送該數量(帶或不帶空終止符;這取決於您)接收器可以從數據報的長度重新構造一個以空字符結尾的字符串。 )

雖然這個函數沒有引發併發問題。

即使多個線程在同一個套接字上調用它,sendto函數也是安全的。但是,如果您在流式套接字上執行此操作,則可能會遇到數據以不可預知的方式交織到字節流中的問題。

相關問題