Variablenzugriff Threadsafe.
-
Hallo,
folgendes. Wenn ich Zwei Threads hab und eine Variable.Thread 1:
while (running) { [...] }Thread 2 sagt irgendwann:
running = FALSE;Ist das Threadsafe, oder brauche ich einen Mutex dafür? Es gibt ja nur einen Thread der schreibt. Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?
Schonmal danke, für eure Mühe!
-
die variable muss glaub ich mit dem schlüsselwort volatile versehen sein.
-
ProgChild schrieb:
Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?
wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...
-
da c++ keine threads kennt, gibt es auch kein schlüsselwort dafür

kann dich nich sgaen, ob das threadsafe is, denk aber schon. Wenn nich machn inlineasm mit
xor running, runningdann isses bstimmt threadsafe.
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
-
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
du meinst mutable
-
dso schrieb:
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
du meinst mutable
nein, er mein schon volatile. Das hat den 'nebeneffekt' das wert immer aus ram gelanden wird. Daruch kann man verhinder das der compiler so optimieret, das running in nem register liegen bleibt, da schneller, und so thread a niemals den wert von b sieht
-
Maxi schrieb:
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
'volatile' sorgt nur dafür, dass die variable auch wirklich im speicher existiert d.h. es verbietet gewisse optimierungen. ...und 'const' ist auch nicht wirklich const

-
ja, hab volatile mit mutable verwechselt. Klugscheißen lohnt sich eben doch nich
-
net schrieb:
Maxi schrieb:
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
'volatile' sorgt nur dafür, dass die variable auch wirklich im speicher existiert d.h. es verbietet gewisse optimierungen. ...und 'const' ist auch nicht wirklich const

Eine Member Variable einer Klasse liegt aber immer im Speicher. Aber volatile müsste hier doch trozdem gesetzt werden. Könnte ja sein, dass der Wert in einem Register zwischen gespeichert wird und nicht neugeladen wird. Oder?
-
net schrieb:
ProgChild schrieb:
Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?
wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...
Das Problem ist noch weitergehend, für CPUs mit mehr als einem Hardware-Thread entstehen auch bei einzelnen Befehlen schon Inkosistenzen zwischen den verschiedenen Caches. Man kommt also nicht daran vorbei, den Cache nach dem Schreiben zu flushen und in anderen Caches diese Line neu einzulesen. Dies geschieht bei volatile-Variablen automatisch und ist u.U. sauteuer.
Auch spiegeln die ASM-Befehle nicht die reale CPU-Architektur wieder, die werden erst wieder in mehrere Mikrobefehle umgewandelt und auch intern parallelisiert ausgeführt. Vielleicht reicht allein das schon, um Probleme zu machen.
-
ProgChild schrieb:
net schrieb:
Maxi schrieb:
volatile variablen können auch dann verändert werden, wenn das objekt const ist.
'volatile' sorgt nur dafür, dass die variable auch wirklich im speicher existiert d.h. es verbietet gewisse optimierungen. ...und 'const' ist auch nicht wirklich const

Eine Member Variable einer Klasse liegt aber immer im Speicher. Aber volatile müsste hier doch trozdem gesetzt werden. Könnte ja sein, dass der Wert in einem Register zwischen gespeichert wird und nicht neugeladen wird. Oder?
Muss nicht.
class foo { public: int val; } void func() { foo f; for(int i=0;i<1000;i++) { f.val++; } }Was spricht dagegen eax als val zu betrachten und mit der schleife drüber zu laufen, ohne val im ram zu allozieren? Wird doch eh von keinem anderen gebraucht. Ok, in ist unwarscheinlich das der Fall eintritt aber es verbietet die keiner nur auf den registern, ohne push/pop oder ram, zu arbeiten so lange das verhanlten nach 'aussen' der norm entspricht.
-
CMatt schrieb:
Was spricht dagegen eax als val zu betrachten und mit der schleife drüber zu laufen, ohne val im ram zu allozieren? Wird doch eh von keinem anderen gebraucht.
Doch! Von dem anderen Thread.
-
Optimizer schrieb:
Das Problem ist noch weitergehend, für CPUs mit mehr als einem Hardware-Thread entstehen auch bei einzelnen Befehlen schon Inkosistenzen zwischen den verschiedenen Caches. Man kommt also nicht daran vorbei, den Cache nach dem Schreiben zu flushen und in anderen Caches diese Line neu einzulesen. Dies geschieht bei volatile-Variablen automatisch und ist u.U. sauteuer.
Okay. Dann einen Mutex, volatile oder kein volatie und hoffen, das es klappt. Ich will nur eine Schleife, die in einem Thread abläuft, aus dem anderen beenden.
Optimizer schrieb:
Auch spiegeln die ASM-Befehle nicht die reale CPU-Architektur wieder, die werden erst wieder in mehrere Mikrobefehle umgewandelt und auch intern parallelisiert ausgeführt. Vielleicht reicht allein das schon, um Probleme zu machen.
Das war auch meine Überlegung. Es könnte ja sein, dass ein long byteweise zugewiesen wird, oder so...
-
net schrieb:
ProgChild schrieb:
Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?
wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...
nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)
-
rüdiger schrieb:
nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)
Was passiert denn im schlimmsten Fall auf einem Multiprozessor System? Wäre ja nicht schlimm, wenn der Thread erst etwas später abgebrochen wird, wenn die Chaches Synchronisiert werden.
-
Es ist klar, dass du Mutexe oder andere Synchronisationsmethoden verwenden musst.
Das folgende Programm sieht von außen ok aus (es sei denn man ist in Multithreading geschult):
extern "C" { #include <pthread.h> #include <unistd.h> } #include <iostream> int flag = 0; void * th(void *) { sleep(5); flag = 1; std::cout << "Counter is now " << flag << std::endl; return NULL; } int main() { pthread_t pid; pthread_create(&pid, NULL, th, NULL); unsigned int counter = 0; while (flag == 0) { ++counter; } pthread_join(pid, NULL); std::cout << "Counter: " << counter << std::endl; }Übersetzt mit
g++ -Wall -W -pedantic -pthread -O2 thread.Cläuft das Programm in eine Endlosschleife.
volatile hilft in diesem Beispiel, ist aber keine allgemeine Lösung. Siehe
-
ProgChild schrieb:
rüdiger schrieb:
nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)
Was passiert denn im schlimmsten Fall auf einem Multiprozessor System? Wäre ja nicht schlimm, wenn der Thread erst etwas später abgebrochen wird, wenn die Chaches Synchronisiert werden.
Verallgemeinert gesagt, sehen verschiedene Threads unterschiedliche Werte, weil jeder seinen eigenen Cache hat. Schreiboperationen sieht eine ganze Zeit lang nur der schreibende Thread selber. Das ist katastrophal.
-
Wobei das auch stark von der Architektur des Systems abhängig ist.
-
Optimizer schrieb:
Auch spiegeln die ASM-Befehle nicht die reale CPU-Architektur wieder, die werden erst wieder in mehrere Mikrobefehle umgewandelt und auch intern parallelisiert ausgeführt.
glaub' nicht. auch wenn's micro'code' heisst, so isses doch meistens so schnell wie ein elektron braucht um in's silizium einzudringen, damit hinten ein anderes rausfällt

rüdiger schrieb:
net schrieb:
ProgChild schrieb:
Hab irgendwo gelesen, dass der lesende Thread inkonsistente Daten lesen könnte, wenn ein lese und ein schreib Thread existieren. Ist das hier auch der Fall?
wenn für's lesen oder schreiben mehr als eine asm-instruction nötig sind, dann brauchste 'nen lock, sonst sollte das ohne gehen...
nicht auf einem Mehr-Prozessor-System (wobei die wahrscheinlichkeit dann wohl schon sehr gering sein dürfte)
jo, beim mehrprozzi haste das problem der verschachtelten bus-nutzung, da kann einer schon die speicherzelle verändert haben, während der andere erst den befehl decodiert hat. aber naja, ich meinte mit meinem posting das zeitscheiben-multitasking mit nur einer cpu. dabei ist ja ein asm-befehl nicht unterbrechbar...
-
net schrieb:
jo, beim mehrprozzi haste das problem der verschachtelten bus-nutzung, da kann einer schon die speicherzelle verändert haben, während der andere erst den befehl decodiert hat. aber naja, ich meinte mit meinem posting das zeitscheiben-multitasking mit nur einer cpu. dabei ist ja ein asm-befehl nicht unterbrechbar...
Okay war jetzt das Resultat, dass ich volatile und Mutexe brauche, um sowas vernünftig zu realisieren, aber eig. volatile in der geg. Situation ausreicht?