Ablauf der Programmausführung während der Thread-Erstellung

8

Ich bin neu in Threads.

Ich habe ein Beispielprogramm geschrieben, um einen Thread zu erstellen.

%Vor%

Nach der Kompilierung lautet die Antwort:

%Vor%

Ich verstehe, dass die Antwort variieren kann, da return 0; aufgerufen werden kann, bevor das printf in func ausgeführt wird. Aber wie kommt es in der Lösung, inside function wird zweimal gedruckt?

Beim Kompilieren mit gcc -o temp thread1.c -lpthread beim ersten Lauf:

%Vor%

beim zweiten Lauf:

%Vor%

Beim Kompilieren mit gcc -pthread -o temp thread1.c Beim ersten Lauf:

%Vor%

Ich habe dieses Verhalten auf

beobachtet %Vor%     
starkk92 04.08.2014, 11:46
quelle

3 Antworten

3

Ich habe dieses Problem auf der gcc-Version 4.6.3 (Ubuntu / Linaro 4.6.3-1ubuntu5), der glib-Version 2.15 mit O2 flag beobachtet. Ohne ein Optimierungs-Flag wird dieses Problem nicht beobachtet.

Warum die Ausgabe seltsam ist
Die C-Sprachspezifikation bezieht sich nicht auf einen bestimmten Compiler, ein Betriebssystem oder eine CPU. Es bezieht sich auf eine abstrakte Maschine, die eine Verallgemeinerung der tatsächlichen Systeme ist. Diese abstrakte Maschine (mindestens bis C99 Spezifikationen) ist single-threaded. Daher müssen Standardbibliotheken (einschließlich printf ) standardmäßig nicht threadsicher sein. Wenn Sie Standard-Bibliotheksfunktionen über die Threads hinweg verwenden (mit einer Bibliothek wie zum Beispiel posix libpthread), sind Sie für das Hinzufügen von Synchronisation (Mutex, Semaphor, Condvar usw.) verantwortlich, bevor Sie auf nicht-eintretende Standardbibliotheksfunktionen zugreifen. Wenn Sie dies nicht tun, kann es von Zeit zu Zeit zu überraschenden Ergebnissen kommen, die Sie auf eigenes Risiko verwenden sollten.

Einige Analysen in der Umgebung, in denen ich dieses Problem reproduzieren kann Wenn ich die Assembly analysiere, die für beide Flags generiert wurde, kann ich keinen signifikanten Unterschied finden (Etwas Bemerkenswertes, printf s werden in puts konvertiert)

Blick auf die Quelle für puts

%Vor%

Das Problem scheint in _IO_putc_unlocked('\n', _IO_stdout) zu liegen. Dies kann den Stream leeren und kann vor dem Aktualisieren des Stream-Status beendet werden.

Lernziele für Multithreading-Codierung
Wenn der Hauptthread zurückgegeben wird, wird der gesamte Prozess beendet. Dies schließt alle anderen Threads ein. So signalisieren Sie allen Children-Threads, dass sie beendet werden sollen (oder verwenden Sie pthread_kill ) und machen Sie entweder den Hauptthread mit pthread_exit oder verwenden Sie pthread_join .

    
Mohit Jain 07.08.2014 06:38
quelle
1

Im Allgemeinen können Sie nicht davon ausgehen, dass printf und verwandte Speicherstrukturen threadsicher sind. Es hängt davon ab, wie die stdio-Bibliothek implementiert wurde. Insbesondere können Fehlfunktionen auftreten, wenn Threads und Prozesse beendet werden, da die Laufzeitbibliothek die Ausgabepuffer normalerweise vor dem Beenden entleert. Ich habe bereits eine solche Art von Verhalten gesehen, und die Lösung ist normalerweise ein Mutex oder Semaphor, um die Ausgabeoperationen zu schützen (genauer gesagt, um die Zugriffe auf FILE-Objekte zu schützen).

    
Giuseppe Guerrini 07.08.2014 07:31
quelle
1

Soweit ich mich erinnern kann, ist das Kompilieren mit "-pthread" gleichzusetzen mit "-D_REENTRANT -lpthread", das ist der einzige Unterschied. Beachten Sie, dass printf und dergleichen nicht reentrant sind, da sie in einem globalen Puffer arbeiten.

Nachdem ich das gesagt habe, war ich leider nicht in der Lage, den interessanten Teil Ihres Problems wiederherzustellen (Ihr printf in der Thread-Zielfunktion scheint zweimal aufgerufen worden zu sein). Jede Methode der Kompilierung (-lpthread und -pthread) gibt mir das gleiche Ergebnis: Ich bekomme die Prints von innerhalb der Hauptansicht, aber keine von den innerhalb des Thread-Ziels (wie du schon erwähnt hast). Ich denke, das ist nur ein Timing-Problem, bei dem das Thread-Ziel nicht vor den Haupt-Exits "herumkommt". In der Tat, nur für 1/100 Sekunde zu schlafen, bevor ich von der Hauptleitung zurückkomme, bekomme ich den Druck der Zielfunktion. Probieren Sie es aus und lassen Sie uns wissen, was Sie sehen:

%Vor%

Ich spielte mit der Verzögerungszeit und sogar mit 1/1000000 Sekunden:     Schlaf (1); Ich bekomme immer noch alle meine erwarteten prints. Wenn die Sleep-Verzögerung abnimmt, ist es wahrscheinlicher, dass das Drucken nicht in der richtigen Reihenfolge erfolgt, was ich erwarten würde.

Also in Bezug auf die mehrfachen Drucke: Wie viele vor mir aufgezeigt haben, operieren printf und ähnliche auf globalen Strukturen und sind nicht reentrant. Ich würde Interesse daran haben, Ihre Ausgabe zu sehen, wenn Sie stdout nach Ihrem printf flushed, alles durch einen Mutex geschützt:

%Vor%

BEARBEITEN

Es tut mir leid, ich war nicht 100% ig klar, als ich vorgeschlagen habe, fflush () oben zu verwenden. Ich glaube, dass das Problem darin besteht, dass Sie zwischen dem Zeitpunkt, zu dem die Zeichen auf den Bildschirm geschoben werden, und dem Löschen des Puffers unterbrochen werden. Wenn der Puffer dann wirklich geleert wird, hast du deine Zeichenfolge effektiv zweimal gedrückt.

    
Don Shankin 07.08.2014 05:49
quelle

Tags und Links