Hallo, ich hab da mal eine blöde Frage!!! Ich verwende in einem c++ Programm unter Linux mehrere Threads die (fast) alle auf die gleiche Ressource zugreifen die mit einer Mutex gegen (quasi) gleichzeitigen Zugriff gesichert ist. Ein Thread jedoch benutzt die Ressource besonders stark so dass die anderen nahezu nicht dran kommen, denn immer wenn sie Rechenzeit bekommen ist die Ressource durch den einen noch gesperrt. Meine Frage: Gibt es irgendeine Möglichkeit den Scheduler zu einem bestimmten Zeitpunkt, z.B. nach "pthread_mutex_unlock", zu veranlassen einen "context switch" durchzuführen ???. Momentan behelfe ich mich damit dass ich immer nach "pthread_mutex_unlock" eine Wartezeit einfüge innerhalb der bestimmt ein "context switch" erfolgt. Das ist natürlich keine schöne Sache. Gruss Stefan
Hallo Μαtthias W.
das war jetzt ein sehr guter Hinweis, ich hab zwar jetzt noch nicht
> sicher_yield()
gefunden aber
sched_yield(void);
denke ich tuts auch!
Danke, sehr gut !!!
Stefan schrieb: > Momentan behelfe ich mich damit dass ich immer nach > "pthread_mutex_unlock" eine Wartezeit einfüge innerhalb der bestimmt ein > "context switch" erfolgt. Da der ja gleich zu Beginn der Wartezeit passiert, kannst du auch einfach eine Wartezeit von 0 angeben. Μαtthias W. schrieb: > sicher_yield() sollte das sein was du suchst. Du meinstest vermutlich sched_yield().
Stefan schrieb: > Hallo, > ich hab da mal eine blöde Frage!!! > > Ich verwende in einem c++ Programm unter Linux mehrere Threads die > (fast) alle auf die gleiche Ressource zugreifen die mit einer Mutex > gegen (quasi) gleichzeitigen Zugriff gesichert ist. Quasi? Nimm eine Multicore-CPU oder ein SMP-System und da ist nix quasi... Übrigens auch der einzige Weg um eine halbwegs realistische Chance zu haben jemals Fehler im Locking aufzudecken. Multithreading mit Single-Core ist wie Gruppensex allein... ;-) > Ein Thread jedoch benutzt die Ressource besonders stark so dass die > anderen nahezu nicht dran kommen, denn immer wenn sie Rechenzeit > bekommen ist die Ressource durch den einen noch gesperrt. Dann ist da etwas falsch designed. Meiner Meinung nach. Was soll MT in so einem Fall bringen? Wie man es trotzdem halbwegs zum Laufen bekommt ist schon beantwortet worden.
Jasch schrieb: > Dann ist da etwas falsch designed. Meiner Meinung nach. Was soll MT in > so einem Fall bringen? Ja, könnte man meinen! Aber in meinem Fall greift die besagte Methode auf eine Hardware-Einheit zu und kann desshalb nicht "reentrant" sein so sehr ich das auch möchte. Also muss ich den Zugriff mit Mutex serialisieren (einer nach dem anderen) und da hilft auch keine Jasch schrieb: > Multicore-CPU oder ein SMP-System Dies gilt im übrigen für alle Komponenten die in einem Rechner nur einmal vorhanden sind !!! Häufig macht man sich die Sache ganz einfach und sperrt sie mit open/close gleich für alle übrigen Nutzer. Das geht in meinem Fall gleich gar nicht.
Stefan schrieb: > Ein Thread jedoch benutzt die Ressource besonders stark so dass die > anderen nahezu nicht dran kommen, denn immer wenn sie Rechenzeit > bekommen ist die Ressource durch den einen noch gesperrt. Dann geht es wohl eher um Prioritäten und Rechenzeit. Du müßtest die Priorität des Threads herunterstufen, nachdem er die Resource gehabt hat. Auch wenn Du mit sched_yield() die CPU abgibst, aber der Thread weiterhin die höchste Priorität hat, wird er weiterrechnen. Das erwähnte sched_yield kann nützen wenn die Threads alle die gleiche Priorität haben. Wenn es deine Applikation erlaubt, kannst Du den Thread auch für ein paar ms schlafen legen, dann kommen die anderen zum Zug. Du müsstest einmal analysieren, warum ein Thread die CPU monopolisiert. - Hat er höhere Priorität als die anderen - Ist er rechenintensiver als die anderen, sodass er länger laufen kann bis zum nächsten Sys-Call
Ich versteht das Problem nicht, die anderen Thread warten doch an der Stelle wo sie die Resource brauchen, sobald sie von dem anderne Thread freigegeben wird kommen sie dran. Der andere Thread muss doch doch auch wieder hinten anstellen.
Peter II schrieb: > Der andere Thread muss doch doch auch > wieder hinten anstellen. Nicht wenn er immer noch der aktive Thread ist und ein paar µs später die Ressource wieder allokiert. Das würde nur funktionieren wenn bei jeder Freigabe der Mutex automatisch ein Contextswitch zu dem nächsten Prozess stattfindet, aber das (ich weiss das jetzt nicht genau) dürfte eigentlich nicht der Fall sein. Und ich denke auch nicht daß ein Mutex eine genaue Reihenfolge einhält weil das ja nicht mit dem Scheduler für die Threads und Prozesse zu synchronisieren ist.
Udo Schmitt schrieb: > wenn bei jeder Freigabe der Mutex > automatisch ein Contextswitch zu dem nächsten Prozess stattfindet, Solche Details sind sicher implementierungsabhängig und hängen vom verwendeten Betriebsystem ab. Im Normalfall erfolgt ein Contex-Switch nur, wenn ein höher priorisierter Thread auf die Mutex wartet oder sonst irgendwie die Zeitscheibe für den Thread aufgebraucht ist. Die Freigabe einer Mutex ist ja auch kein Grund den Thread zu unterbrechen, schließlich hat es das selbe Anrecht auf Rechenzeit wie die anderen, wartenden Threads und ein Context-Switch verschwendet nur CPU-Leistung.
Klaus Falser schrieb: > Die Freigabe einer Mutex ist ja auch kein Grund den Thread zu > unterbrechen, schließlich hat es das selbe Anrecht auf Rechenzeit wie > die anderen, wartenden Threads und ein Context-Switch verschwendet nur > CPU-Leistung. Genau das meine ich. Wenn der eine Prozess in 95% seiner Laufzeit die Ressource über den Mutex blockiert, dann ist die Wahrscheinlichkeit daß der Mutex frei ist wenn der nächste Prozess drankommt nur 1/20. Es ist irrig anzunehmen, daß alle auf den Mutex wartenden Prozesse schön der Reihe nach drankommen. Sie kriegen eine Zeitscheibe und wenn der Mutex frei ist kriegen sie ihn, ansonsten wird zum nächsten Prozess/Thread abgegeben. Insofern wäre es ein Lösungsansatz nach jedem Freigeben des Mutex in dem Prozess der die Ressource so oft belegt ein yield() einzubauen, oder auch nur bei jedem 2. oder 5. freigeben. Ein anderer Ansatz wäre, einen eigenen Thread zu schreiben, der alle Anfragen auf die Ressource kanalisiert und ggf. 'gerechter' verteilt.
Peter II schrieb: > Ich versteht das Problem nicht, die anderen Thread warten doch an der > Stelle wo sie die Resource brauchen, sobald sie von dem anderne Thread > freigegeben wird kommen sie dran. Der andere Thread muss doch doch auch > wieder hinten anstellen. genau dieses "hintenanstellen" will ich ja erreichen, aber es ist leider so dass sich der eine Thread die Ressource wieder schnappt bevor durch einen "context-switch" einer der anderen dran ist!!!
Dann musst du halt die Priorität für Wartende kontinuierlich erhöhen und wieder runtersetzen, wenn sie mal dran waren.
könnte man das nicht mit einem 2. Mutex lösen? Ich habe jetzt nicht weiter nachgedacht. 1. Thread 1.Mutex nehmen 1. Thread 2.Mutex nehmen 1. Thread 1.Mutex freigeben 1. Thread Arbeiten 1. Thread 2.Mutex freigeben wenn jetzt ein 2. Thread kommt, dann hat er ja den 1.Mutex schon, damit kommt dann Thread 1 nicht weiter und beim contextwechsel ist dann Thread 2 dran.
Tut das Problem bitte nicht verkomplizieren !!! Es reicht wenn ich dafür sorge dass immer dann ein "context switch" durchgeführt wird wenn die Ressource frei ist. Bisher hatte ich das mit einer Wartezeit gelöst (ist aber unschön, desshalb die Frage). pthread_yield() und/oder sched_yield() sind genau die richtigen Werkzeuge um das "hintenanstellen" zu erzwingen (bei gleicher Priorität)
Stefan schrieb: > Hallo Μαtthias W. > > > das war jetzt ein sehr guter Hinweis, ich hab zwar jetzt noch nicht >> sicher_yield() > gefunden aber > > sched_yield(void); > > denke ich tuts auch! Das war auch gemeint. Die Autokorrektur in Android hat leider zugeschlagen. Matthias
Stefan schrieb: > pthread_yield() und/oder sched_yield() sind genau die richtigen > Werkzeuge um das "hintenanstellen" zu erzwingen (bei gleicher Priorität) Zumindest dass die anderen Prozesse dann drankommen wenn die Ressource frei ist. Falls allerdings dein Prozess der die Ressource oft braucht sie ständig alloziert und wieder freigibt dann würde er auch sehr oft yielden was dazu führt daß er immer weniger Rechenzeit hat weil er seine Zeitscheibe immer gleich wieder abgibt. Wie gesagt, meine Idee wäre den Zugriff zu der Ressource gezielt in einem eigenen Thread zu steuern, aber das war ein Schuss ins blaue da ich nicht weiß was du tun willst. Peter IIs Idee habe ich jetzt ehrlich gesagt noch nicht durchgedacht.
Nachtrag: Peter II schrieb: > 1. Thread 1.Mutex nehmen > 1. Thread 2.Mutex nehmen > 1. Thread 1.Mutex freigeben > 1. Thread Arbeiten > 1. Thread 2.Mutex freigeben könnte funktionieren, wenn das "Thread Arbeiten" wensentlich länger dauert als das allozieren der Mutexe, wenn der eine Thread allerdings sehr oft die Ressource für sehr kurze Zeit alloziert bringt es nicht so viel. Allerdings müsste man nochmal gründlich über Dead Locks nachdenken, auf die Schnelle sehe ich aber nix problematisches.
Was macht den dein Thread wenn er den Mutex nicht kriegt? Kann er nebenbei noch was anderes machen? Und wie lange benötigt er die geschützte Resource, was kommt dann?
Stefan schrieb: > Häufig macht man sich die Sache ganz einfach und sperrt sie mit > open/close gleich für alle übrigen Nutzer. Die andere Variante ist, daß grundsätzlich nur ein Thread direkt auf die Ressource zugreift und Zugriffsanforderungen von den anderen Threads annimmt und koordiniert. Die können dann weitermachen, solange der Zugriffsthread auf die Hardware wartet. Klaus Falser schrieb: > Im Normalfall erfolgt ein Contex-Switch nur, wenn ein höher > priorisierter Thread auf die Mutex wartet Oder auf irgendwas anderes, sei es ein File/Device, ein Socket, Semaphore oder auch einfach bei einem sleep, wo er nur auf das Ablaufen der Zeit wartet. > Die Freigabe einer Mutex ist ja auch kein Grund den Thread zu > unterbrechen, Doch, denn höherpriore Threads könnten gerade auf die Freigabe warten. > schließlich hat es das selbe Anrecht auf Rechenzeit wie die anderen, Es gibt Prioritäten, und höherpriore Threads haben auch ein höheres Anrecht.
Stefan schrieb: > Jasch schrieb: >> Dann ist da etwas falsch designed. Meiner Meinung nach. Was soll MT in >> so einem Fall bringen? > > Ja, könnte man meinen! > Aber in meinem Fall greift die besagte Methode auf eine Hardware-Einheit > zu und kann desshalb nicht "reentrant" sein so sehr ich das auch möchte. OK, klar. Wobei Reentranz etwas anderes meint, Deine Methode ist ziemlich sicher reentrant. > Also muss ich den Zugriff mit Mutex serialisieren (einer nach dem > anderen) und da hilft auch keine Nun ja, wieso sollen überhaupt mehrere Threads direkt drauf zugreifen, bringt doch offensichtlich keinen Vorteil? > Jasch schrieb: >> Multicore-CPU oder ein SMP-System > > Dies gilt im übrigen für alle Komponenten die in einem Rechner nur > einmal vorhanden sind !!! Klar. Sollte übrigens nicht etwa "helfen" - sondern vor der Vorstellung "quasi-gleichzeitig" warnen, weil das eben heutzutage oft ganz real gleichzeitig ist. Wobei man auf nur einmal vorhandene Komponenten auch nicht MT zugreift - genau weil es nix bringt. Wie soll man sich z.B einen MT-Zugriff auf die Tastatur vorstellen, jeder Thread bekommt mal irgendeinen Tastendruck mit? Da müsstest Du wohl mal genauer beschreiben was Du eigentlich tust - dann kann man es auch verstehen und bessere Hinweise geben. > Häufig macht man sich die Sache ganz einfach und sperrt sie mit > open/close gleich für alle übrigen Nutzer. Das geht in meinem Fall > gleich gar nicht. Rolf Magnus hat geschrieben wie man sowas macht. Das impliziert natürlich recht schnell etwas wie ein Betriebssystem mit Treibern, Queues, Blah, usw. usf.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.