posix thread verständnisfrage
-
liebe cpp-gemeinde,
ich bin neu hier im forum und hoffe auch gleich an der richtigen adresse zu sein.
ich arbeite mich derzeitig in posix threads ein, mir ist im grunde soweit vieles klar, bei weitem aber leider nicht alles:
woher kommt die exakte zuordnung zwischen mutex und der zu blockierenden resource?beispiel (ausschnitt aus einer von einem thread aufzurufenden funktion):
1: pthread_mutex_lock (&mutexsum);
2: dotstr.sum += mysum;
3: pthread_mutex_unlock (&mutexsum);hier wird eine globale datenstruktur dotstr durch einen mutex gesperrt.
woher weiß der mutex also welchen speicherbereich er zu sperren hat und woher nicht und wie geschieht die im detail? (im quellcode ist eine solche zuordnung explizit nicht angegeben).
hinzukommend: ist es möglich einzelne member einer klasse durch einen mutex zu sperren, vorausgesetzt der objektzustand wird durch potentielle änderungen nicht ungültig (will ich hier einfach mal so anehmen).
in den materialien die ich bisher dazu hatte wurde zu sowas keinerlei aussage getroffen. wäre also super wenn mir da jemand auf die sprünge helfen könnte.allerbesten dank!
Grüße
AU
-
Diese Zuordnung geschieht durch den Programmierer.
Ein Mutex hat die Eigenschaften, dass er nur einmal gleichzeitig gelockt werden kann, und, dass er dafür sorgt, dass Veränderungen an Variablen korrekt gesehen werden.
Dies kann man ausnutzen, um bestimmte Speicherbereiche zu schützen.
In deinem Beispiel wird dotstr.sum verändert. Deshalb nimmt man im allgemeinen an, dass der Mutex genau diese Variable schützt. Das ist reine Konvention.
-
danke ponto für die antwort.
ich will da mehr ins detail als es evtl durch meinen post durchkammal angenommen im mutex lock block würden 3 mainthread variablen stehen, der lock würde sich auf alle 3 variablen beziehen (richtig?).implizit also.
du sagtest "die zuordnung geschieht durch den programmierer", das seh ich so streng gesehen nicht am quellcode heraus um ehrlich zu sein, denn in allen beispielen wird nur implizit der mutex zugewiesen, nämlich durch den block den der mutex umschließt. aber nirgens wird explizit mutex.lockVar(myVar) oder sowas aufgerufen.
mal angenommen man würde mit nem debugger über das stückchen quellcode von oben drübergehen und bei 1: stehenbleiben. der mutex wird gelockt. soweit so gut, aber für welchen speicherbereich, steht bis dahin noch lange nicht fest.
ich für mich würde es zur compilezeit logisch erklären können: analyse aller lock blöcke und zuordnung der mutexes an die variablen durch den compiler (gebunden über variablenNamen). aber ob es tatsächlich so ist, wär meine frage.
und falls dem so sein sollte: wo wird der spaß dann abgelegt?Grüße und Danke!
AU
-
Da wird nirgendswo was abgelegt. Der Kompiler macht nichts. Er sorgt nur dafür, dass die Garantien vom Mutex gelten. Mutexe locken keinen Speicherbereich per se. Wenn ein anderer Thread trotz gelocktem Mutex in deine dotstr.sum reinschreibt, wird das durch nichts verhindert und ist ein Fehler.
-
oder anders ausgedrückt
mutexe locken keinen speicher, sondern einen codeabschnittlock(); //es ist garantiert, dass sich in diesem bereich immer nur ein thread befindet unlock();
oder nochmal anders
lock(); x++; //wird nur von einem thread gleichzeitig ausgeführt unlock(); x++;//wird von beliebig vielen threads gleichzeitig ausgeführt
von der implementierung her kannst dus dir z.B. so vorstelln:
lock() { if(lock_besetzt) { lege_thread_schlafen(); } } unlock() { wecke_einen_schlafenden_thread(); }
-
ok, nun stellt sich die sicht ja doch anders dar als ich das bisher annahm.
mutex lockt codeabschnitt der betreten wird.(und nicht, wie angenommen, den speicherbereich)
dh allein dadurch kann ich nicht sicherstellen, dass die resource doch irgendwo noch beschrieben wird, halt nur nicht durch den gleich codeabschnitt sofern er durch mehrere threads gerufen wird.
für eine ("echte") sperrung der resource wie ich das hier egtl dacht, würd ich dann nen monitor nehmen, dh ne methode die schreibenden zugriff hat, und durch nen mutex gelockt wird. diese methode wird dann durch diverse (nicht gleiche) threads gerufen - sofern benötigt. dass ein thread mit der bearbeitung fertig ist signalisiert man dann über ne condition variable.
bin ich da jetzt richtig?
-
Ja was du wolltest war ein Monitor.
Allerdings ist ein Monitor ein Sprachkonstrukt das von der Programmiersprache unterstützt
werden muss.
D.h. der Compiler fügt beim kompilieren locks und ggf. condition variablen in
den Monitor ein, wohingegen die posix locks einfach in einer Bibliothek zur Verfügung
gestellt werden.aber bezogen auf dein erstes beispiel könntest dus so machen:
class dotstr { public: void add(int mysum) { lock(); sum += mysum; unlock(); } int get() { int tmp; lock(); tmp = sum; unlock(); return tmp; } private: int sum; };
damit hättest du lesenden und schreibenden zugriff auf die daten, es wäre garantiert,
dass nur ein thread gleichzeittig drauf zugreift und die daten können nirgends anders
verändert werden da sie privat sind.