2017-02-16 22 views
0

Hier ist ein einfaches Programm, das ich geschrieben habe. Es schafft 10 Threads in einem for-Schleife und jeden Thread druckt den Wert von i:Pthread nicht korrekt drucken

#include <stdio.h> 
#include <pthread.h> 
void* basic_function(void *num){ 
    int cur_num = *(int*)num; 
    printf("Current thread number is :%d\n", cur_num); 
    return NULL; 
} 

int main(int argc, const char * argv[]) { 
    pthread_t thread_id [10]; 
    void * exit_status[10]; 

    for (int i = 0; i < 10; i++){ 
     pthread_create(&thread_id[i], NULL, basic_function, &i); 
     printf("i is: %d\n", i); 
    } 


    for (int i = 0; i<10; i++){ 
     pthread_join(thread_id[i], &exit_status[i]); 


    return 0; 
} 

Ich denke, die Ausgabe etwas wie einige Druckanweisungen von 0 bis 9, in der richtigen Reihenfolge aussehen soll:

Current thread number is: 0 
i is: 0 
Current thread number is: 1 
i is: 1 
Current thread number is: 2 
i is: 2 
... 

Aber stattdessen meine Ausgabe lautet:

i is: 0 
i is: 1 
i is: 2 
i is: 3 
i is: 4 
i is: 5 
Current thread number is: 6 
Current thread number is: 6 
i is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
i is: 7 
Current thread number is: 7 
i is: 8 
Current thread number is: 9 
Current thread number is: 9 
i is: 9 

Warum 6 Thread mehrfach erstellt? Warum werden einige Threads nicht erstellt? Und warum bekomme ich immer unterschiedliche Ausgaben, wenn ich das Programm starte?

Antwort

1

Da das Argument, das an die Thread-Funktion übergeben wird, auf die gleiche Variable verweist - i.

Und als die Variable i wird ständig von der main Funktion aktualisiert werden, erhalten die Fäden immer den neuesten Wert zum Zeitpunkt ihrer laufenden und die Fäden zu tun, dass mit dem main Verfahren parallel. Darüber hinaus kann es vorkommen, dass die Threads auf die Variable zugreifen, sobald die Schleife bereits beendet ist. In diesem Fall ist das Verhalten nicht definiert.

Die Lösung ist, entweder eine Kopie von i auf dem Heap zuzuweisen und den Zeiger auf die Kopie zu übergeben. Oder eine andere etwas schmutzige Lösung ist, den i Zeiger zu übergeben, als Argument übergeben und dann im Thread wieder in int konvertieren. Dies beruht darauf, dass int kleiner als der Zeiger ist, was ziemlich üblich ist, aber auf einer obskuren Architektur möglicherweise nicht wahr ist (wahrscheinlich nicht der Fall für solch kleine Zahlen).

+0

Ich verstehe Ihre erste Lösung. Aber ich weiß nicht, wieso man 'i' auf einen Zeiger anwenden kann, um das Problem zu lösen. Ich denke, es hat den gleichen Effekt wie 'pthread_create (& thread_id [i], NULL, basic_function, & i)', was ich in meinem Beitrag getan habe. – HalfOfRain

+0

Nein, es hat nicht den gleichen Effekt, weil das Umsetzen auf einen Zeiger eine Kopie der Ganzzahl erzeugt, die vom Zeiger übernommen wird. Nicht tragbar, wie Zbynek sagte, aber zuverlässig, wenn es funktioniert – LWimsey