wie schreibe ich ein singleton für multithreads



  • NickHappy schrieb:

    hustbaer hat recht! Der Code ist tatsächlich nicht threadsafe.

    CMyClass * CMyClass::GetInstance()
    {
      static CMyClass instance;
      return &instance;  
    }
    

    Ich dachte bis eben, dass alle globalen Varibalen und alle statischen Varibalen vor Programmstart (in undefinierter Reihenfolge) initialisiert werden. Das stimmt so jedoch nicht uneingeschränkt. Entschuldigung.

    Habs noch mal nachgeschlagen. So gehts (mit Double-Locking)

    static Singleton* getInstance()
    {
      if ( !pInstance ) 
      {
        taskLock();
        if ( !pInstance )
          pInstance = new Singleton;
        taskUnlock();
      }
      return pInstance ;
    }
    

    Lies das vom LordJaxom verlinkte Paper vom Scott Meyers & Andrei Alexandrescu. Du bist gerade dabei die übliche Kette "hey, so gehts", "nö, geht doch nicht", "aber so gehts", "nö, geht auch nicht" etc. durchzuackern die da drinnen beschrieben ist:

    http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

    Multithreadind ist die Hölle, und bestraft wird (fast) jeder der sich für schlau hält 😉



  • hustbaer schrieb:

    Multithreadind ist die Hölle, und bestraft wird (fast) jeder der sich für schlau hält 😉

    Ist mehr ein C++ Compiler Problem, als ein Multithreading Problem.

    Of critical importance is the observation that compilers are not constrained
    to perform these steps in this order! In particular, compilers are sometimes
    allowed to swap steps 2 and 3.



  • hustbaer schrieb:

    Multithreadind ist die Hölle, und bestraft wird (fast) jeder der sich für schlau hält.

    ... weil er OOP, design patterns und C++ mit ins spiel bringt 😃



  • vista schrieb:

    hustbaer schrieb:

    Multithreadind ist die Hölle, und bestraft wird (fast) jeder der sich für schlau hält.

    ... weil er OOP, design patterns und C++ mit ins spiel bringt 😃

    Nein, weil er glaubt einfache, funktionierende Lösungen optimieren zu können ohne sie dabei kaputtzumachen. Lösungen wie z.B.:

    Foo& Foo::GetInstance()
    {
        ScopedLock lock(s_mutex);
        if (!s_instance)
            s_instance = new Foo();
        return *s_instance;
    }
    

    @Leser: ich würde nicht sagen dass es ein C++ Problem ist. Wer mit Threads arbeitet und anfängt diverse Dinge zu "optimieren" kann auch in Java oder .NET Sprachen schnell über seine eigenen "Schlauheit" stolpern.



  • Den zuerst geposteten Code habe ich nicht erfunden (oder optimiert), sondern er nennt sich "Meyer's Singleton" und ist demzufolge von Meyer.

    Du bist gerade dabei die übliche Kette "hey, so gehts", "nö, geht doch nicht", "aber so gehts", "nö, geht auch nicht" etc. durchzuackern die da drinnen beschrieben ist...

    Unsinn.

    Multithreadind ist die Hölle, und bestraft wird (fast) jeder der sich für schlau hält.

    Ich habe meinen Irrtum zugegeben. Nun weide dich nicht an den Fehlern anderer, sondern sieh zu, dass du selber ja nie einen (Fehler) machst. *g*



  • NickHappy, ich habe selbst schon genug Fehler gemacht, und es kommen wohl laufend welche dazu. Darum geht's mir aber nicht. Vielmehr darum dass dein 2. Vorschlag den du mit "Habs noch mal nachgeschlagen. So gehts (mit Double-Locking)" angepriesen hast wieder falsch ist (BTW: du meinst wohl "double checked locking" -- probier den Suchbegriff mal in Google, da findest du haufenweise zu dem Thema, u.A. an Stelle ~6 das hier verlinkte Paper).

    Und dass du diesen 2. Code auch nicht selbst erdacht hast, sondern irgendwo nachgeschlagen, beweist nur wieviel falscher Code "da draussen" zu finden ist. Tragisch aber wahr. Und genau deswegen reite ich auch so auf dem Thema herum.

    Und noch einmal: bitte lies das hier: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
    Auf Seite 3 ("3 The Double-Checked Locking Pattern") steht GENAU der Code den du als 2. gepostet hast, und im weiteren dann auch haarklein erklärt warum er falsch ist.



  • hustbaer schrieb:

    @Leser: ich würde nicht sagen dass es ein C++ Problem ist. Wer mit Threads arbeitet und anfängt diverse Dinge zu "optimieren" kann auch in Java oder .NET Sprachen schnell über seine eigenen "Schlauheit" stolpern.

    Im allgemeinen ja, aber hier kommen die Probleme schon auch von C++. In Java wird die instnz nicht != null sein, obwohl sie noch garnicht vollstndig erzeugt ist.



  • Den Code habe ich aus meiner "Deeply Embedded Vorlesung". Werde meinen Prof. nochmal drauf aufmerksam machen, dass der Code u.U. Probleme machen kann.



  • Leser schrieb:

    ...In Java wird die instnz nicht != null sein, obwohl sie noch garnicht vollstndig erzeugt ist.

    Eine gültige Referenz auf ein Objekt, das noch nicht vollständig erzeugt ist ?
    Das klingt mir nach einem echten Problem !!

    Gruß,

    Simon2.



  • Der Pointer pInstance (bzw. in Java halt Referenz) kann sowohl in C++ als auch in Java != 0 sein bevor das Objekt fertig konstruiert ist, wenn man keine explizite Memory Barrier reinschreibt.
    In Java 1.5 bzw. auch mit MSVC8 geht es wenn man pInstance volatile macht, mit "normalen" C++ Compilern bzw. vor Java 1.5 darf man sich allerdings nicht darauf verlassen...


Anmelden zum Antworten