Keyworld 'volatile' in Zusammenhang mit Parallel Programming [Erledigt]



  • Ich frage mich gerade, ob ich Thread.MemoryBarrier() korrekt verstanden habe. Ich sehe das so:
    Thread.MemoryBarrier() macht zwei Dinge:
    1. Es verhindert, dass die CLR bzw. der Compiler Vertauschungen von Lese-und Schreibeoperaitonen vornimmt, die ueber das Thread.MemoryBarrier() gehen.
    2. Wenn Thread.MemoryBarrier() augerufen wird, dann werden alle lokal gecachten Variablen neu geladen. Damit wird verhindert, dass ein Thread immer nur seine lokal gecachten Werte liest.

    Ist das soweit korrekt?

    Die ganze Geschichte mit volatile und MemoryBarrier() scheint eine ziemlich haarige Sache zu sein. Nicht mal auf der MSND-Website ist es korrekt beschrieben.



  • Das kann man wohl so stehen lassen.

    albahari:

    The simplest kind of memory barrier is a full memory barrier (full fence) which prevents any kind of instruction reordering or caching around that fence.

    Die Fehler auf der MSDN-Seite hast Du schon angedeutet.

    Weiter:

    A good approach is to start by putting memory barriers before and after every instruction that reads or writes a shared field, and then strip away the ones that you don’t need. If you’re uncertain of any, leave them in. Or better: switch back to using locks!

    Und deshalb lasse ich die Finger davon und auch von volatile.



  • Ja sieht ganz so aus als sollte man besser die Finger davon lassen.

    Wenn man allerdings lockfreie Algorithmen/Datenstrukturen implementieren will, die trotzdem Thread-Safe sind, dann scheint man teilweise nicht darum herum zu kommen. Aber dann muss man sich schon sehr gut ueberlegen was man tut.



  • icarus2 schrieb:

    Wenn man allerdings lockfreie Algorithmen/Datenstrukturen implementieren will, die trotzdem Thread-Safe sind, dann scheint man teilweise nicht darum herum zu kommen.

    Es gibt noch die Interlocked-Klasse, für nicht-blockierende Synchronisation:
    http://www.albahari.com/threading/part4.aspx#_Interlocked

    icarus2 schrieb:

    Aber dann muss man sich schon sehr gut ueberlegen was man tut.

    Volatile & Memory-Barriers sind schlicht und einfach nicht Debugfähig und in realen Projekten kaum zu beherrschen. Und so lange MS diese Mittel nicht konsequent dokumentieren kann, werde ich sie nicht einsetzen.
    Denn alles Überlegen hilft nicht, wenn nicht fehlerfrei dokumentiert ist, was dabei passiert.



  • µ schrieb:

    icarus2 schrieb:

    Wenn man allerdings lockfreie Algorithmen/Datenstrukturen implementieren will, die trotzdem Thread-Safe sind, dann scheint man teilweise nicht darum herum zu kommen.

    Es gibt noch die Interlocked-Klasse, für nicht-blockierende Synchronisation:
    http://www.albahari.com/threading/part4.aspx#_Interlocked

    Die kannte ich bereits, aber danke fuer den Hinweis.

    µ schrieb:

    icarus2 schrieb:

    Aber dann muss man sich schon sehr gut ueberlegen was man tut.

    Volatile & Memory-Barriers sind schlicht und einfach nicht Debugfähig und in realen Projekten kaum zu beherrschen. Und so lange MS diese Mittel nicht konsequent dokumentieren kann, werde ich sie nicht einsetzen.
    Denn alles Überlegen hilft nicht, wenn nicht fehlerfrei dokumentiert ist, was dabei passiert.

    👍


  • Administrator

    Was habt ihr denn gegen sowas?

    class Program
    {
      private volatile bool m_isRunning;
      private Thread m_thread;
    
      private void DoWork()
      {
        while(m_isRunning)
        {
          Console.WriteLine("Blubber");
        }
      }
    
      public void Start()
      {
        m_isRunning = true;
        m_thread = new Thread(this.DoWork);
        m_thread.Start();
      }
    
      public void Stop()
      {
        m_isRunning = false;
        m_thread.Join();
      }
    
      public static void Main(String[] args)
      {
        var p = new Program();
        p.Start();
    
        Thread.Sleep(1000);
    
        p.Stop();
      }
    }
    

    Genau für sowas kann man volatile in C# und Java verwenden. Und genau sowas ist in der MSDN Dokumentation zu volatile auch vermerkt.

    Das ihr auf die Thread.MemoryBarrier() Funktion verzichten wollt, dafür habe ich durchaus Verständnis, aber wieso ihr auch volatile in diesen Topf werfen wollt, leuchtet mir nicht ein.

    Grüssli



  • Lies mal hier unter 'The volatile keyword'.

    Dort steht unter anderem:

    The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered.

    Est ist auf der MSDN Seite falsch dokumentiert und die Verwendung scheint sehr heikel zu sein.

    Deswegen sollte man aus meiner Sicht besser die Finger davon lassen.


  • Administrator

    icarus2 schrieb:

    Lies mal hier unter 'The volatile keyword'.

    Dort steht unter anderem:

    The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered.

    Est ist auf der MSDN Seite falsch dokumentiert und die Verwendung scheint sehr heikel zu sein.

    Deswegen sollte man aus meiner Sicht besser die Finger davon lassen.

    Ich finde es als ziemlich verkehrt, die MSDN Aussage als falsch hinzusetzen. volatile hat eben immer nur Auswirkungen auf eine Variable. Das Beispiel das dort aufgeführt wird, hat bereits zwei Variablen im Einsatz. Sobald man mit solchen Abhängigkeiten unter mehreren Variablen arbeitet, sollte man sofort zu lock greifen. Aber eben für so einfache Dinge, wie eine Abbruchbedingung ist volatile absolut ausreichend. Die MSDN Aussage ist meiner Meinung nach absolut richtig. Auch wenn im Beispiel von Albahari a und b mit einer 0 belegt werden, so wurde immer der aktuellste Werte der Variable x und y ausgelesen. x und y sind völlig unabhängig. volatile schreibt nicht vor, wann in x geschrieben wird in Abhängigkeit zu y oder umgekehrt. Davon schreibt auch die MSDN rein gar nichts.

    Es ist mir ehrlich gesagt etwas ein Rätsel, wie man überhaupt auf so eine Vermutung kommen kann, dass a und b nicht 0 sein könnten wegen volatile . Nur weil zwei Variablen mit volatile gekennzeichnet wurden, soll plötzlich eine Abhängigkeit zwischen den beiden bestehen? Wie kommt man auf sowas? 😕

    Grüssli



  • @Dravere:
    Ich habe nochmals im Tutorial von Albahari und die MSDN Dokumentation gelesen und ich denke, dass du recht hast.

    Das volatile gibt nur die Garantie, dass Memoryzugriffe auf die gleiche Variable nicht umgeordnet werden. Auch sorgt es dafuer, dass keine veralteten Werte gelesen werden und die Werte immer sofort ins Memory geschrieben werden, d.h. nicht lokal gechached werden. Bei verschiedenen Variabeln, die mit volatile deklariert wurden, koennen allerdings Umordnungen stattfinden. Ist das soweit richtig?

    Das heisst das volatile Keyword ist im Prinzip kein Ersatz fuer MemoryBarriers. Ist das korrekt?


  • Administrator

    icarus2 schrieb:

    Das volatile gibt nur die Garantie, dass Memoryzugriffe auf die gleiche Variable nicht umgeordnet werden. Auch sorgt es dafuer, dass keine veralteten Werte gelesen werden und die Werte immer sofort ins Memory geschrieben werden, d.h. nicht lokal gechached werden. Bei verschiedenen Variabeln, die mit volatile deklariert wurden, koennen allerdings Umordnungen stattfinden. Ist das soweit richtig?

    Ja, zumindest habe ich das so aus der MSDN verstanden, bzw. ich konnte in der MSDN nirgends lesen, dass solche Umordnungen bei verschiedenen Variablen verboten sein sollten. Daher gehe ich davon aus, dass sie erlaubt sind.

    icarus2 schrieb:

    Das heisst das volatile Keyword ist im Prinzip kein Ersatz fuer MemoryBarriers. Ist das korrekt?

    Ja, das definitiv.

    Grüssli



  • Alles klar. Danke dir.


Anmelden zum Antworten