2013-06-26 13 views
5

Zastanawiam się, co się dzieje, gdy dwa wątki wywołują tę samą funkcję w tym samym czasie, a funkcja jest klientem UDP, który wysyła tekst przez gniazdo.Co stanie się, jeśli więcej niż jeden pthread używa tej samej funkcji?

Biorąc pod uwagę poniższy kod, uruchomiłem go, ale nie mam jeszcze żadnego błędu. Zastanawiam się, czy to powinno być rozbite, ponieważ wątki używają tego samego źródła (funkcji, zmiennej, adresu IP, portu) w tym samym czasie i jak dzielą się źródłami? Mogę sobie wyobrazić, że poniższy kod jest błędnym użyciem wielowątkowości, czy mógłbyś wyjaśnić mi, w jaki sposób powinny być używane wątki, aby wątek korzystał z tej funkcji, której nie używają żadne inne wątki? Innymi słowy, w jaki sposób może być bezpieczny dla wątków?

jako przykład kodu C na Linuksie:

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

Nie ma problemu z wywołaniem tej samej funkcji (każdy wątek ma własny, niezależny kontekst wykonania i stos). Mogą * istnieć * problemy z dostępem do stanu współdzielonego (w tym stan współdzielony w wywołaniach biblioteki) - rozważ samodzielną analizę kodu, aby sprawdzić, jaki jest wspólny stan i ewentualnie skupić się na tym pytaniu. – user2246674

+1

Piękno automatycznych zmiennych polega na tym, że wszystko działa ... automatycznie. –

+1

'thread1_fcn()' i 'thread12_fcn()' powinny nadal być zadeklarowane, aby wziąć argument 'void *', aby dopasować to, czego 'pthread_create()' oczekuje. – jxh

Odpowiedz

3

Ponieważ tworzenie i zamknąć gniazdo wewnątrz msg_send, nic specjalnego się nie stanie. Wszystko będzie dobrze.

3

Nie ma żadnego problemu z kodem. Każdy wątek, nawet jeśli działa na tym samym kodzie, ma osobny stos, więc oddzielny zestaw zmiennych, na którym działa. Żadne zmienne nie są udostępniane.

1

Twój kod wywołuje niezdefiniowane zachowanie, ponieważ wątki przekazują małe ciągi literałów jako argument message, ale funkcja próbuje wysłać 1000 bajtów zaczynając od adresu podstawowego message.

Ponieważ sendto jest często bezpośrednim połączeniem z systemem operacyjnym, albo wyślesz dużo śmieci przez UDP (albo gorzej: informacje ważne dla bezpieczeństwa!), Albo wywołanie systemowe wykryje dostęp do pamięci poza granicami i powrót -1 z errno ustawionym na coś takiego jak EFAULT (prawdopodobnie bez wysłania jakichkolwiek danych).

Ponieważ message jest ciągiem znaków, należy obliczyć jego długość, a następnie wysłać tylko taką ilość (z lub bez terminatora zerowego, który należy do Ciebie) Odbiornik może zrekonstruować łańcuch zakończony wartością zerową z długości datagramu.)

Funkcja nie powoduje jednak problemów z współbieżnością.

Funkcja sendto jest bezpieczna, nawet jeśli wiele wątków wywołuje ją na tym samym gnieździe. Jeśli zrobisz to na gnieździe strumieniowym, najprawdopodobniej napotkasz problemy z przeplatanymi danymi do strumienia bajtów w nieprzewidywalny sposób.

Powiązane problemy