Seite 1 von 1

Threadsicheres Singleton

Verfasst: Donnerstag 3. September 2009, 16:39
von snafu
Den Mechanismus hat sicher schon der ein oder andere gesehen, aber ich glaube es gibt noch keinen eigenen Thread dazu.

Code: Alles auswählen

import threading

class Singleton(object):
    """A thread-safe class acting like a singleton"""
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance

Code: Alles auswählen

In [1]: from singleton import Singleton

In [2]: s1 = Singleton()

In [3]: s2 = Singleton()

In [4]: s1 is s2
Out[4]: True

Re: Threadsicheres Singleton

Verfasst: Donnerstag 3. September 2009, 18:30
von Defnull
Dein thread-safe Singleton ist nicht thread-safe, wenn es zwischen Zeile 9 und 10 zu einem Kontext-Wechsel kommt. Es sollte so aus sehen:

Code: Alles auswählen

import threading
class Singleton(object):
    """A thread-safe class acting like a singleton"""
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        with cls._lock:
            if not cls._instance:
                cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance

Verfasst: Donnerstag 3. September 2009, 20:17
von theliquidwave
Kann mir mal jemand genau erklären, was ein Singleton ist und warum der jetzt Thread-safe ist?

Danke :lol:

Verfasst: Donnerstag 3. September 2009, 20:25
von sma
Ein Singleton ist das einzige Exemplar einer Klasse. Oder anders ausgedrückt, alle Exemplare der Klasse sind nicht nur gleich sondern auch identisch.

Und threadsafe ist nicht das Singleton-Objekt, sondern der Konstruktor `__new__` der beim ersten Aufruf das Objekt erzeugt - genau einmal und nicht öfters.

Stefan

Verfasst: Donnerstag 3. September 2009, 20:26
von Defnull

Verfasst: Donnerstag 3. September 2009, 23:12
von snafu
Ist es eigentlich sinnvoll, dass ein Singleton Argumente annehmen kann? Denn schließlich verschwinden ja jegliche Argumente, die nach dem ersten Bau übergeben werden, ohnehin sang- und klanglos im Nirvana. Ist es vielleicht besser, einen anderen Weg zu gehen und eine Exception zu werfen, sobald versucht wird, ein Singleton zum zweiten Mal zu instanzieren? Welcher Weg wäre hier zu bevorzugen?

@Chrisber: Und um das gerade Erläuterte zu gewährleisten, ist der Trick hier, dass sich sozusagen in den Erstellungsprozess der Klasse eingemischt wird. Es wird diesmal nicht mit den Attributen des Exemplars gearbeitet, wie man es häufig in der __init__-Methode einer Klasse findet, sondern direkt mit den Klassenattributen. Die überschriebene __new__-Methode, welche noch vor __init__ aufgerufen wird, prüft, ob bereits ein Exemplar erstellt wurde. Wenn nicht, wird eins erstellt und an das Attribut _instance gebunden und dieser Wert gilt nun dauerhaft. Falls es schon ein Exemplar gibt - _instance also nicht mehr mit None belegt ist -, passiert nichts und es bleibt somit beim zuerst erstellten Exemplar. Zuletzt wird dieses dann zurückgeliefert.

Verfasst: Freitag 4. September 2009, 11:51
von snafu
Das was ich mit den Argumenten gesagt hab, erscheint mir immer schlüssiger. Dann vielleicht doch besser so:

Code: Alles auswählen

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if args or kwargs:
            raise TypeError, 'Singleton does not take any argument'
        if not cls._instance:
            cls._instance = object.__new__(cls)
        return cls._instance