Multithreading sicheres Singleton Pattern



  • Ich dachte bisher, dass für diesen Zweck das double checked singleton pattern da wäre, allerdings musste ich eben beim googlen lesen, dass es nicht funktioniert.

    Wie macht man denn nun eine Singleton Klasse multithreading sicher?



  • Doch das funktioniert schon. Nur nicht überall.

    Du kannst es doch einfach ohne Check machen, dann ist es auf jeden Fall Threadsafe aber ein bisschen langsamer.



  • Hab nun endlich die Zeit gefunden mir das genauer anzuschauen und könnte man das nicht einfach so machen:

    class Singleton
    {
      public:
       Singleton& inst()
       {
           static int lock = 0;
           if( lock == 1 )
               while( lock == 1 );
           lock = 1;
           static Singleton instance_;
           lock = 0;
           return instance_;
       }
    }
    

    Wenn eine Zuweisung an einen int atomar ist würde das doch eine mehrfachinitialisierung verhindern, jedenfalls unter Systemen mit nur einer CPU.
    Oder geht das so doch nicht?



  • User-- schrieb:

    class Singleton
    {
      public:
       Singleton& inst()
       {
           static int lock = 0;
           if( lock == 1 )
               while( lock == 1 );
           lock = 1;
           static Singleton instance_;
           lock = 0;
           return instance_;
       }
    }
    

    Wenn eine Zuweisung an einen int atomar ist würde das doch eine mehrfachinitialisierung verhindern, jedenfalls unter Systemen mit nur einer CPU.
    Oder geht das so doch nicht?

    hmm, könnte nicht der erste Thread bis kurz vor die lock = 1; anweisung kommen, und dann der Zweite Thread auch? Dann wäre das wieder unsicher, oder?



  • wie wäre es mit pthread_mutex_lock oder ähnlichem?

    auf bald
    oenone



  • User-- schrieb:

    Hab nun endlich die Zeit gefunden mir das genauer anzuschauen und könnte man das nicht einfach so machen:

    class Singleton
    {
      public:
       Singleton& inst()
       {
           static int lock = 0;
           if( lock == 1 )
               while( lock == 1 );
           lock = 1;
           static Singleton instance_;
           lock = 0;
           return instance_;
       }
    }
    

    Wenn eine Zuweisung an einen int atomar ist würde das doch eine mehrfachinitialisierung verhindern, jedenfalls unter Systemen mit nur einer CPU.
    Oder geht das so doch nicht?

    Das geht so nicht, denn der andere Thread muss überhaupt nicht mitbekommen, dass du lock verändert hast. Was spricht gegen folgendes?

    extern "C" void create_instance();
    
    class Singleton
    {
       public:
          static Singleton& inst()
          {
             static pthread_once_t once_control = PTHREAD_ONCE_INIT;
             pthread_once(&once_control, create_instance);
             return *instance;
          }
    
       private:
          Singleton() {}
          Singleton(Singleton const & other);
    
          friend void create_instance();
          static Singleton * instance;
    };
    
    extern "C" void create_instance() {
       static Singleton inst;
       Singleton::instance = &inst;
    }
    
    Singleton * Singleton::instance = NULL;
    


  • Wollte OS spezifischen Code eigentlich vermeiden, aber ich vermute mal, ich habe wohl doch keine andere Wahl.

    Danke 🙂


Anmelden zum Antworten