004
29.10.2004, 15:09 Uhr
ao
(Operator)
|
Nochn Versuch:
Der Optimizer darf Variablenzugriffe wegoptimieren, wenn sie wirkungslos sind bzw. wenn für ihn keine Wirkung erkennbar ist (mal vereinfacht ausgedrückt). Beispiel:
C++: |
bool bEventDetected = false; /* Zeigt an, ob ein Ereignis eingetreten sit */
/* Warten auf ein Ereignis */ while (!bEventDetected) { sleep (1); /* bisschen warten */ }
/* Wenn wir hier ankommen, liegt ein Ereignis vor, und wir verarbeiten es */ ...
|
Stell dir vor, du bist in einem Multithreaded-Programm. Mit dem oben gezeigten Code wartet ein Thread auf ein Ereignis (könnte z.B. ein Mausklick sein) und geht dann weiter.
Die Information, dass das Ereignis eingetreten ist, wird von einem anderen Thread bereitgestellt:
C++: |
extern bool bEventDetected;
/* Ereignis anzeigen */ bEventDetected = true; ...
|
Wenn der Compiler den oberen Code übersetzt, erkennt er, dass nichts in der Schleife den Wert von bEventDetected verändert, er könnte also (optimierend) folgenden vermeintlich äquivalenten Ersatzcode erzeugen:
C++: |
if (!bEventDetected) /* Flagge nur einmal prüfen */ { while (1) /* wenn sie false ist, bleibt sie es auch -> Endlosschleife */ { sleep (1); } }
|
Beim Übersetzen des anderen Threads könnte der Compiler erkennen, dass der Schreibzugriff auf bEventDetected wirkungslos ist, weil die Variable anschließend nirgendwo abgefragt wird. Aggressiv optimierend könnte er also die komplette Schreibaktion wegwerfen, und der Handshake zwischen den Threads würde nicht funktionieren.
Jetzt kommt volatile ins Spiel: Mit volatile sagen wir dem Compiler: Alle Zugriffe auf diese Variable so ausführen, wie sie im Quellcode stehen. Auch wenn du glaubst, dass es Unsinn ist, optimier es trotzdem nicht weg.
ao |