Multithreadingaufruf verhält sich wie Funktion

Hallo!

Ich erstelle mit dem Visual Studio eine neue Konsolenanwendung mit MFC-Unterstützung. Im main-Teil rufe ich dann zwei Threads auf. Nachstehendes zeigt wie ich das mache:

AfxBeginThread(MeinThread1, NULL);
AfxBeginThread(MeinThread2, NULL);

Der Compiler meldet keinen Fehler. Wenn ich das Programm laufen lasse tut es fast genau das was ich möchte. Jeder der beiden Threads gibt 11 mal eine Meldung aus. Thread1 „Hallo“ und Thread2 „Ciao“. Wenn ich dann aber das Ausgabefenster mir anschaue sehe ich elf mal hintereinander unterbrechungsfrei „Hallo“. Danach elf mal unterbrechungsfrei „Ciao“. DAs lässt darauf schließen, dass die main eine Funktion aufruft und wenn die abgearbeitet ist, ruft sie die zweite auf und wenn das auch passiert ist, wird die main weiter abgearbeitet.
Dazu bräuchte ich aber keinen Thread! Das könnte auch eine simple FUnktion. Beim Threading ist der Vorteil das beide Threads parallel arbeiten und die main ebenfalls nachdem beide aufgerufen wurden sofort weiterarbeitet, ohne zu warten bis beide nacheinander fertig sind. Das ist doch Quatsch was da läuft! Im Ausgabefenster müsste durcheinander „Hallo“ und „Ciao“ erscheinen. Also zum Beispiel „HalloHalloCiaoHalloCiaoCiao“ und so weiter.
Was läuft da schief? Ich kenne bis jetzt Threads nur aus QT (recht unbekannte Form von C++ aus der Linuxwelt um es ohne lange Rede zu umschreiben). Hat jemand eine Idee? Fehlt vielleicht eine Art Priorität? Aber wenn alle gleichberechtig sein sollen macht das glaube ich nicht wirklich Sinn. An den Includes kann es nicht liegen, weil das habe ich in meiner Verzweiflung schon mit Ausprobieren herausbekommen.
Ich bin für jede Zuschrift dankbar!

Gruß Christian

Hi,
wenn der Thread wirklich nur 11 mal ein Wort ausgeben soll, ist er damit schon fertig bevor es überhaupt zu einen Taskswitch kommt. Versuch mal die Tasks etwas (mehr) Zeit verschwenden zu lassen.

Grüße,
Daniel Raffler

Hi!
Der Hinweis war echt super! Ich habe jetzt von 11 auf 251 umgestellt. Jetzt passiert folgendes 17 mal kommt Thread 1 unterbrechungsfrei hintereinander, dann 17 mal Thread 2 unterbrechungsfrei hintereinander mit seiner Meldung. Das die Abstände dann so regelmäßig sind, ist das normal?
Und wann wird welcher Teil abgearbeitet? Für mich wirkt das gerade so, dass der Computer erst ein bischen an Thread 1 rechnet, dann an Thread 2, zu Abwechslung dann mal wieder an Thread 1, usw. Oder liegt das am trivialen Inhalt des Threads (mit Inhalt ist jetzt gemeint was er tun soll)?
Vielen Dank bis hier erstmal!!!

Gruß Christian

Hi Christian,

Deine Beobachtung ist korrekt. Jeder Thread bekommt eine bestimmte Zeit (sog. Zeitscheibe) zugeordnet, in der er rechnen kann, danach schaltet das Betriebssystem zum nächsten Thread weiter. Wenn Du ein Mehrprozessorsystem hättest, würdest Du gemischtere Ausgaben bekommen.

Die Arbeit, die ein Thread verrichtet, spielt erstmal keine Rolle. Sobald die Zeitscheibe abgelaufen ist, wird der Zustand des Threads gesichert, und der nächste Thread kommt dran. Änderst Du die Priorität einen Threads, so kommt er einerseits öfter dran, andererseits kann sich die grösse der Zeitscheibe ändern.

Gruss,

Herb

Hallo Christian,

Der Hinweis war echt super! Ich habe jetzt von 11 auf 251
umgestellt. Jetzt passiert folgendes 17 mal kommt Thread 1
unterbrechungsfrei hintereinander, dann 17 mal Thread 2
unterbrechungsfrei hintereinander mit seiner Meldung. Das die
Abstände dann so regelmäßig sind, ist das normal?
Und wann wird welcher Teil abgearbeitet? Für mich wirkt das
gerade so, dass der Computer erst ein bischen an Thread 1
rechnet, dann an Thread 2, zu Abwechslung dann mal wieder an
Thread 1, usw. Oder liegt das am trivialen Inhalt des Threads
(mit Inhalt ist jetzt gemeint was er tun soll)?

Das mit der Zeitscheibe (Time-Slice) beim Time-Sharing Multitask hat Herb ja schon erklärt.
Hinzu kommt aber noch, dass ein Task seine Zeit-Scheibe früzeitig abgeben kann. Entweder durch geziehlte Betriebssyszem-Aufrufe oder aber weil er z.B. auf eine Eingabe von der Tastatur wartet.

MfG Peter(TOO)

Hi!
Als erstes möchte ich danke sagen. DAnn aber noch eine Frage nachreichen. Angenommen ich hätte ein System mit zwei CPUs auf einem Mainboard. Müsste ich dann selbst noch was machenb, dass sich beide CPUs die Arbeit teilen und es gemischter wird, oder geht das dann automatisch?
Oder kann ich irgendwie beeinflussen wie lange jeder Thread Zeit bekommt?

Gruß Christian

Hi,

wenn Du zwei oder mehr CPUs hast, dann musst Du in der Regel nichts tun, das Betriebssystem wird die Threads verteilen. Du kannst allerdings (abhängig vom Betriebssystem) die Threads einer bestimmten CPU zuweisen, wenn Du willst.
Wie Peter schon beschrieben hat, kann ein Thread seine Rechenzeit selbst verkürzen. Die Grösse der Zeitscheibe pro Thread einzustellen wäre m. E. nur möglich, wenn der Thread nach einer bestimmten Zeit seine Zeitscheibe selber abgeben würde. Das macht allerdings kaum Sinn.

Gruss,

Herb

Hallo,

Wie Peter schon beschrieben hat, kann ein Thread seine
Rechenzeit selbst verkürzen. Die Grösse der Zeitscheibe pro
Thread einzustellen wäre m. E. nur möglich, wenn der Thread
nach einer bestimmten Zeit seine Zeitscheibe selber abgeben
würde. Das macht allerdings kaum Sinn.

Bei Timeshare-System, kann die Zeitscheibe indirekt über die Priorität beeinflusst werden. Mit einer höheren Priorität kommst du meist einfach öfters drann, die Scheiben bleiben aber meist gleich gross.

Data General, oder war’s General Data, die beiden verwechsle ich immer, hatte ein MultiUser-TimeSlice-BetriebsSystem bei dem reine CPU-Zeit (also reine Rechenarbeit) und I/O-Zeit (Disk-, Drucker-Zugriffe, usw.) getrennt verwaltet wurden. Wenn der Task eine Weile keine I/O-Zugriffe machte, bekamm er beim nächsten mal eine „grössere Scheibe“ für seine I/O zugeteilt.

Das TimeShare-Verfahren gehöhrt zu den so genannten preemtiven Verfahren, d.h. einem Task wird bei überschreiten seiner Zeit, vom Scheduler, einfach die CPU „weggenommen“.
Im Gegensatz dazu steht das kooperativen Verfahren (z.B. Win 3.x) wo der Task die CPU freiwillig abgeben muss. Hier besteht aber das Problem, dass wenn ein Task in eine Endlos-Schlaufe gerät alle anderen Tasks „verhungern“ weil sie die CPU nie zugeteilt bekommen. Kooperative Systeme werden oft bei Steuerungen (Zustands-Automaten) eingesezt, da sie sehr einfach zu realisieren sind und bei Steuerungen, oft, nur auf Grund einer Änderung eines Eingangs, kurze Berechnungen ausgeführt werden müssen.

MfG Peter(TOO)

Hi,
dass indirekt über die Priorität die Laufzeit eingestellt werden kann ist mir klar, ich meinte ja nur, dass das Einstellen einer Laufzeit pro Thread keinen Sinn macht, da der Verwaltungsaufwand zu gross wäre.

Den nonpreemptiven Unsinn, den Win3.x angestellt hat, haben wir glücklicherweise hinter uns.

War es im Tannenbaum, wo was davon stand, dass manche Betriebssysteme die Threads mit höherer Priorität öfter rechnen lassen als Threads mit geringerer Prio?

Viele Grüsse,

Herb

Hallo Herb,

dass indirekt über die Priorität die Laufzeit eingestellt
werden kann ist mir klar, ich meinte ja nur, dass das
Einstellen einer Laufzeit pro Thread keinen Sinn macht, da der
Verwaltungsaufwand zu gross wäre.

Wenn du ganzzahlige Vielfache der Slice-Time nimmst, nimmst beschränkt sich der zusätzliche Aufwand auf das Kopieren einer Zahl, beim Task-wechsel und ein Decrement und ein if bei jedem Tick.

Den nonpreemptiven Unsinn, den Win3.x angestellt hat, haben
wir glücklicherweise hinter uns.

Wie schon gesagt, bei Automaten wird das noch sehr oft verwendet.

War es im Tannenbaum, wo was davon stand, dass manche
Betriebssysteme die Threads mit höherer Priorität öfter
rechnen lassen als Threads mit geringerer Prio?

Keine Ahnung, ich hab da schon viel zu lange Praxis mit (und wohl auch schon zu viele BS für uP geschrieben).

MfG Peter(TOO)