Thread mit C++ unter Linux



  • Hallo!
    Ich bin schon über einer Stunde auf der Suche nach einem Beispielcode dafür. Entweder sind sie hoch kompliziert oder funktionieren nicht. Kann mir da einer vielleicht helfen?





  • Danke dazu habe ich auch was gefunden

    #include <stdio.h>
    #include <pthread.h>
    
    void *print_char (void *ch)
    {
      int i;
      while(true){}
      return NULL;
    }
    
    int main ()
    {
      char ch1='-', ch2='*';
      pthread_t p1, p2;
    
      pthread_create (&p1, NULL, print_char, &ch1);
      pthread_create (&p2, NULL, print_char, &ch2);
    
      pthread_join (p1, NULL);
      pthread_join (p2, NULL);
    
      printf ("\nENDE");
      return 0;
    }
    

    Das einzige Problem ist das es keine Threads gibt! Das Hauptprogramm macht erst weiter wenn die Threads beendet ist was ja aber eigentlich nicht der Fall sein sollte



  • Nun ja, was meinst du wohl, was pthread_join macht?



  • Gibt es denn nicht soetwas wie CreateThread von Windows für Linux?



  • asdfasdf schrieb:

    Gibt es denn nicht soetwas wie CreateThread von Windows für Linux?

    pthread_create(..) ??



  • Doch, nennt sich pthread_create.

    ...



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Das einzige Problem ist das es keine Threads gibt!

    Doch, du hast zwei mit pthread_create erzeugt. Sie laufen bereits. Beobachte doch mal die Prozessorauslastung mit top .

    Das Hauptprogramm macht erst weiter wenn die Threads beendet ist was ja aber eigentlich nicht der Fall sein sollte

    Mittels pthread_join wartest du auf beide Threads, bis sie beendet werden. Leider laufen sie in einer Endlosschleife, werden also niemals beendet.





  • Ja gut dann müsste es ja aber eigentlich gehen wenn man das join weglässt

    #include <stdio.h>
    #include <pthread.h>
    
    void *print_char (void *ch)
    {
      int i;
      while(true){}
      return NULL;
    }
    
    int main ()
    {
      char ch1='-', ch2='*';
      pthread_t p1, p2;
    
      pthread_create (&p1, NULL, print_char, &ch1);
      pthread_create (&p2, NULL, print_char, &ch2);
    
      ...
      return 0;
    }
    

    Ader er hält trotzdem da



  • Wo ist da? Auch solltest du vorsichtig sein, wird das Ende von main erreicht und der Prozess beendet, werden auch ohne Vorwarnung deine Threads beendet.



  • Ein korrektes Beispiel wäre das hier.

    #include <stdio.h> 
    #include <pthread.h> 
    
    void *print_char(void *ch) 
    { 
      int i = 0; 
      while (true) {} 
      return NULL; 
    } 
    
    int main() 
    { 
      char ch1='-', ch2='*'; 
      pthread_t p1 = 0, p2 = 0; 
    
      pthread_create(&p1, NULL, print_char, &ch1); 
      pthread_create(&p2, NULL, print_char, &ch2); 
    
      pthread_join(p1, NULL);
      pthread_join(p2, NULL);
    
      return 0; 
    }
    

    Okay, ich muss das jetzt mal zerpflücken, weil das selbst im korrigierten Zustand ein "mieser" Stil ist.

    In C++ haben C Includes nichts zu suchen! Daher ...

    #include <cstdio>
    extern "C" { 
    #include <pthread.h>
    }
    

    Man sollte immer die C++ Variante eines C Includes verwenden, wenn vorhanden. Ansonsten gehört ein "extern C" drumrum.

    Variablen immer einen initialen Wert verpassen!

    pthread_t p1 = 0, p2 = 0;
    

    Der Unterschied zwischen C++ und C im Fall vom GCC (mit seinem C99 Standard) ist der, dass der GCC im Falle von C die Variablen mit einem Defaultwert initialisiert (ist den Kernelentwicklern zu verdanken, die haben da ne Menge Druck bei den GCC Entwicklern gemacht). Nur dummerweise trifft das für C++ (g++ oder gcc -lstdc++) nicht zu. Außerdem gilt in C++ sowieso das RAII-Prinzip (Resource Allocation is Initialization)...

    Nach dem Erstellen eines Threads muss das weitere Verfahren festgelegt werden.

    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
    

    Es kommt ganz darauf an, mit welchen Attributen der Thread erstellt wurde. Entweder joinable oder eben nicht. Danach MUSS man den Thread detachen (pthread_detach = pthread_raise_zombie :D) oder joinen, ansonsten ist das Verhalten undefiniert. Bei einem detach entlässt man den Thread in die freie Wildbahn, man kommt also nicht mehr an ihn heran. Man muss also dafür sorgen, dass er normal endet, bevor der ihn umfassende Process endet. Bei einem join warted man darauf, dass der Thread normal zurückkehrt. Ist im Prinzip sowas wie ein "wait_for_thread"...

    Ganz wichtig: Hat man einen GCC 4.4 oder größer zur Verfügung, besteht eine hohe Wahrscheinlichkeit, dass die StdC++ Lib Version 4 dabei ist und die beinhaltet native C++ Threads. Die sollte man dann auf jeden Fall nehmen, denn pthreads sind für C und nicht für C++. Das Signalkonzept in pthreads beißt sich mit C++ Exceptions.

    Hier ein C++0x Beispiel.

    #include <iostream>
    #include <thread>
    #include <mutex>
    
    std::mutex mutex_variable;
    
    void printString(const std::string& str)
    {
      std::lock_guard<std::mutex> lock(mutex_variable);
      std::cout << str << std::endl;
    }
    
    int main()
    {
      std::thread t1(printString, "Eins");
      std::thread t2(printString, "Zwei");
      std::thread t3(printString, "Drei");
      std::thread t4(printString, "Vier");
    
      t1.join();
      t2.join();
      t3.join();
      t4.join();
    
      return 0;
    }
    

    Man muss nicht unbedingt ein LockGuard verwenden, aber ist für dieses Beispiel am besten, da einmal "cout" mehrfach verwendet wird. Man kann ja mal gaghalber den LockGuard rausnehmen... sieht lustig aus 🙄

    Kompiliert wird mit "g++ -std=c++0x -lpthread ..." pthrads ist hier ein Trugschluss, da wird wohl noch irgend ein Rest verwendet, denn die nativen C++ Threads basieren nicht auf pthreads sondern auf Kernel Threads.


Anmelden zum Antworten