[C] thread safety
-
warum reden hier eigentlich alle ueber Locks etc? Alles was der Benutzer brauch ist eine getThreadNumber() und ein Array statt einer globalen Variable. Dann kann er sich jegliche Synchronisation auch komplett ersparen
-
asc schrieb:
In Objektorientierten Sprachen, kann ich das imho noch leichter machen, und weniger Fehleranfällig:
Genau davon ist doch die ganze Zeit die Rede.
Allgemein "in Objektorientierten Sprachen" wäre ich damit aber vorsichtig, da z.B. in Java der Destruktor nicht sofort bei Ende des Scopes aufgerufen wird, sondern eventuell irgendwann später. Dort sollte man finally verwenden.
So ein RAII-Lock-Objekt ist letztendlich nur eine syntaktische Abkürzung; sicherlich komfortabel, aber kein konzeptioneller Vorteil von OOP. Ich würde ein einfaches lock/unlock in C trotzdem vorziehen, weil es klarer verständlich ist, als wenn sich das unlock hinter einer geschweiften Klammer versteckt; gerade bei Nebenläufigkeit halte ich es für keine keine gute Idee, Dinge wegzukapseln, die der Programmierer besser im Blick haben sollte.
Wenn euch jemand an eurem Code rumpfuscht und mittendrin returns einfügt, ohne Ressourcen freizugeben, habt ihr ganz andere Probleme.
Wenn man C++ programmiert, kann man aber nicht einfach lock/unlock aufrufen, eben weil z.B. unerwartet geworfene Exceptions das unlock umgehen könnten, sondern muss RAII verwenden. C++-Fans spinnen RAII aber immer gerne als großen Vorteil.
-
rapso schrieb:
*fricky schrieb:
knivil schrieb:
Schwachsinn, was hat OOP mit Overhead bei Multithreading zu tun?
na, z.b. dass man versucht ist, dinge in klassen bzw. in ein oo-design zu pressen, obwohl es keinen nennenswerten vorteil bringt.
du verstehst den vorteil wohl nur nicht. gerade in bezug auf multithreading ist es wichtig guten code zu haben
es ist doch oft wichtig, guten code zu haben. das ist bei multithreading auch nicht anders.
rapso schrieb:
OOP erlaubt dir automatische dinge zu nutzen die fehler ausschliessen, z.b. verzweigung aus einer funktion ohne unlock vom mutex.
aber das ist doch ein völlig banaler fehler, den man meistens schon durch scharfes hinschauen erkennt. aber gut, mag ja sein, dass verhindern von trivialfehlern manchmal der einzige grund ist, oop einzusetzen.
asc schrieb:
void Bar::Foo() { mach_was_ohne_lock(); { Lock l; if(!mach_was()) return; // Ohne umständliche Freigaben... mach_was_anderes(); } mach_was_ohne_lock(); }
Ist zudem auch gegen return und ähnliches sicher (Ich liebe RAII)...
hihi, und dann kommt einer und wundert sich, was die geschweiften klammern da sollen (weil ja weder ein if/while/for/sonstwas davor steht) und löscht sie weg.
-
Thread Saviour schrieb:
Bonjour!
und in bar ... muss ich dann rausfinden, in welchem thread ich bin und mir den dazugehörigen file_descriptor beschaffen.
wie würde das am geschicktesten gehen?Lass foo den Filedescriptor als Funktionsergebnis liefern und gib ihn dann bar als weiteres Argument mit. Du brauchst den dann nicht global, sondern nur als lokale Variable in der Threadfunktion anzulegen.
-
Ciao
Blue-Tiger schrieb:
warum reden hier eigentlich alle ueber Locks etc? Alles was der Benutzer brauch ist eine getThreadNumber() und ein Array statt einer globalen Variable. Dann kann er sich jegliche Synchronisation auch komplett ersparen
Ja, ich denke darauf wird es hinauslaufen. Oder ich benutze tls, das gibts wohl für den gcc (den ich benutze) auch.
(und über locks reden die anderen, weil sie wieder mal einen der heiligen kriege der informatik auskämpfen)
@Belli:
ich kann leider die deklaration der funktionen nicht ändern.
-
Blue-Tiger schrieb:
warum reden hier eigentlich alle ueber Locks etc? Alles was der Benutzer brauch ist eine getThreadNumber() und ein Array statt einer globalen Variable. Dann kann er sich jegliche Synchronisation auch komplett ersparen
getThreadNumber(), ja, klar. Blödsinn. Thread-ID wenn schon. Und Thread-IDs haben so die Angewohnheit total beliebige Nummern, meist min. 32 Bit breit, zu sein. Also wird ihm ein Array nicht viel bringen.
-
hustbaer schrieb:
Blue-Tiger schrieb:
warum reden hier eigentlich alle ueber Locks etc? Alles was der Benutzer brauch ist eine getThreadNumber() und ein Array statt einer globalen Variable. Dann kann er sich jegliche Synchronisation auch komplett ersparen
getThreadNumber(), ja, klar. Blödsinn. Thread-ID wenn schon. Und Thread-IDs haben so die Angewohnheit total beliebige Nummern, meist min. 32 Bit breit, zu sein. Also wird ihm ein Array nicht viel bringen.
Nein, ich meinte getThreadNumber(), nicht getThreadID. Es gibt sehr wohl Thread-Libs, welche die IDs "durchnummerieren", OpenMP zum Beispiel. Und wenn der OP nicht eine solche einsetzt, muss eben eine (synchronisierte) ID->Nummer Map her, das versteht sich wohl von selbst.
EDIT: oder eine (insofern die Implementierung threadsafe ist nichtmal notwendigerweise synchronisierte) ID -> Filedescriptor Map. Vermutlich sind die meisten Maps aber nicht Threadsafe, also waere das wohl eine langsamere Sache.
Eine andere Idee waer, die globalen Descriptoren einfach Thread-global zu machen (widerum: OpenMP kann das, k.A. wie's mit anderen APIs ausschaut).
-
tfa schrieb:
Selten so viel Unsinn gelesen.
*fricky ist ein Troll, einfach ignorieren. Er ändert übrigens seinen Nick hin und wieder, aber man erkennt ihn sofort.
-
MFK schrieb:
Er ändert übrigens seinen Nick hin und wieder, aber man erkennt ihn sofort.
ja, ab gestern trage ich das sternchen vorn. ~ war mir auf dauer zu langweilig.
-
Blue-Tiger schrieb:
hustbaer schrieb:
Blue-Tiger schrieb:
warum reden hier eigentlich alle ueber Locks etc? Alles was der Benutzer brauch ist eine getThreadNumber() und ein Array statt einer globalen Variable. Dann kann er sich jegliche Synchronisation auch komplett ersparen
getThreadNumber(), ja, klar. Blödsinn. Thread-ID wenn schon. Und Thread-IDs haben so die Angewohnheit total beliebige Nummern, meist min. 32 Bit breit, zu sein. Also wird ihm ein Array nicht viel bringen.
Nein, ich meinte getThreadNumber(), nicht getThreadID. Es gibt sehr wohl Thread-Libs, welche die IDs "durchnummerieren", OpenMP zum Beispiel. Und wenn der OP nicht eine solche einsetzt, muss eben eine (synchronisierte) ID->Nummer Map her, das versteht sich wohl von selbst.
EDIT: oder eine (insofern die Implementierung threadsafe ist nichtmal notwendigerweise synchronisierte) ID -> Filedescriptor Map. Vermutlich sind die meisten Maps aber nicht Threadsafe, also waere das wohl eine langsamere Sache.
Eine andere Idee waer, die globalen Descriptoren einfach Thread-global zu machen (widerum: OpenMP kann das, k.A. wie's mit anderen APIs ausschaut).
OK.
Libs welche Thread-Nummern vergeben anstelle von IDs sind aber die Ausnahme und nicht die Regel. Weiters muss eine obere Schranke bekannt sein wenn man ein unsynchronisiertes Array verwenden möchte.
IMO halt keine sehr hilfreiche Antwort wenn man schreibt "is doch alles ganz einfach, machst du XYZ und gut" (sinngemäss), XYZ aber leider nur in ganz wenigen Spezialfällen möglich/anwendbar ist.Was synchronisierte Maps angeht: is dann aber auch nimmer "ganz einfach". Kann man gleich diverse TLS-Funktionen (WinAPI, pthreads, ...) verwenden. Bei pthreads bekommt man z.B. netterweise auch "deleter" mitgeliefert. Gerade wenn man File-Handles offen hat kann das denke ich sehr nützlich sein.