Threadsicheres Singleton

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

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
Zuletzt geändert von Defnull am Donnerstag 3. September 2009, 20:18, insgesamt 1-mal geändert.
Bottle: Micro Web Framework + Development Blog
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Kann mir mal jemand genau erklären, was ein Singleton ist und warum der jetzt Thread-safe ist?

Danke :lol:
Grüßle.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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
Antworten