Forum: Compiler & IDEs Threads und Mutex


von Stefan (Gast)


Lesenswert?

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

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

sicher_yield() sollte das sein was du suchst.

Matthias

von Stefan (Gast)


Lesenswert?

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 !!!

von Rolf M. (rmagnus)


Lesenswert?

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().

von Jasch (Gast)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Udo S. (urschmitt)


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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.

von Udo S. (urschmitt)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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!!!

von Klaus W. (mfgkw)


Lesenswert?

Dann musst du halt die Priorität für Wartende kontinuierlich erhöhen und 
wieder runtersetzen, wenn sie mal dran waren.

von Peter II (Gast)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

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)

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von Udo S. (urschmitt)


Lesenswert?

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.

von Udo S. (urschmitt)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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?

von Rolf Magnus (Gast)


Lesenswert?

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.

von Jasch (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.