effizientes threadsicheres Singleton in C ++
Dem üblichen Muster für eine singleton-Klasse ist so etwas wie
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
inst = new Foo(...);
return *inst;
}
Aber es ist mein Verständnis, dass diese Lösung nicht thread-sicher, da 1) Foo Konstruktor könnte mehr als einmal aufgerufen werden (die möglicherweise oder möglicherweise nicht wichtig ist), und 2) inst möglicherweise nicht vollständig aufgebaut, bevor er wieder in einem anderen thread.
Eine Lösung ist, wickeln Sie einen mutex um die ganze Methode, aber dann werde ich die Zahlung für die Synchronisation overhead lange, nachdem ich es tatsächlich zu brauchen. Eine alternative ist so etwas wie
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
{
pthread_mutex_lock(&mutex);
if(inst == NULL)
inst = new Foo(...);
pthread_mutex_unlock(&mutex);
}
return *inst;
}
Ist das der richtige Weg, es zu tun, oder gibt es irgendwelche Fallstricke, die ich beachten sollte? Zum Beispiel, gibt es keine statische Initialisierung, um Probleme, die auftreten könnten, d.h. inst garantiert immer NULL sein, das erste mal getInst genannt wird?
InformationsquelleAutor der Frage user168715 | 2010-04-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre Lösung wird als 'double checked-locking' und die Art und Weise, die Sie geschrieben haben es ist nicht threadsicher.
Diese Meyers/Alexandrescu Papier erklärt, warum - aber das Papier ist auch weitgehend missverstanden. Es begann die 'double-checked locking ist unsicher in C++" meme - aber seine tatsächliche Schlussfolgerung ist, dass double-checked-locking in C++ umgesetzt werden können, sicher, es erfordert nur die Verwendung von memory-Barrieren, die in einem nicht offensichtlichen Ort.
Das Papier enthält pseudocode demonstriert, wie memory-Barrieren, um sicher zu implementieren, die DLCP, so sollte es nicht schwierig für Sie, um Ihre richtige Umsetzung.
InformationsquelleAutor der Antwort Joe Gauterin
Wenn Sie mit C++11, hier ist eine richtige Weg, um dies zu tun:
Nach neuer Norm gibt es keine Notwendigkeit zu kümmern, dieses problem nicht mehr. Objekt wird bei der Initialisierung nur gemacht werden, indem ein thread, andere threads warten, bis es abgeschlossen ist.
Oder Sie können mit std::call_once. (mehr info hier)
InformationsquelleAutor der Antwort Sat
Verwenden
pthread_once
, die garantiert, dass die Initialisierung Funktion einmal ausgeführt wird atomar.(Auf Mac OS X nutzt es eine spin-lock. Weiß nicht, die Umsetzung von anderen Plattformen.)
InformationsquelleAutor der Antwort kennytm
Herb Sutter spricht über die double-checked-locking in CppCon 2014.
Unten ist der code, den ich in C++implementiert 11 basierend auf:
können Sie auch überprüfen komplette Programm finden Sie hier: http://ideone.com/olvK13
InformationsquelleAutor der Antwort qqibrow
TTBOMK, die nur gewährleistet ist, thread-sicheren Weg, dies zu tun, ohne sperren wäre zu initialisieren alle Ihre singletons vor Sie jemals eine Diskussion starten.
InformationsquelleAutor der Antwort sbi
Ihre alternative heißt "double-checked-locking".
Dort existieren könnte, multi-threaded-Speicher-Modelle, bei denen es funktioniert, aber POSIX garantiert nicht ein
InformationsquelleAutor der Antwort
Ass singleton-Implementierung verwendet double-checked-locking-Muster für thread-Sicherheit, die Sie sich beziehen können, wenn Sie möchten.
Finden Sie Quellcode hier.
InformationsquelleAutor der Antwort baris.aydinoz
Tut TLS arbeiten? https://en.wikipedia.org/wiki/Thread-local_storage#C_and_C++
Beispielsweise
Aber wir müssen auch einen Weg, um es zu löschen explizit, wie
InformationsquelleAutor der Antwort Joe C