2010-12-13 17 views
3

In den meisten Code, den ich geschrieben habe oder überprüft, Verriegelung wird über Zusammensetzung erreicht, wo eine Klasse besitzt einen kritischen Abschnitt oder Mutex:Locking durch Vererbung statt Zusammensetzung

class MyClass 
{ 
    Mutex mMutex; 
}; 

und wenn wandelbar Mitglieder können potenziell sein über mehrere Threads zugegriffen wird, wir das Schloss über RAII wie diese erwerben und freigeben:

void MyClass::Method() 
{ 
    Lock lock(mMutex); 
    // ... 
} 

Heute habe ich einige Code überprüft, wo der Code Verriegelung über Vererbung wurde Umsetzung wie folgt aus:

class MyClass : public Mutex 
{ 
    // ... 
}; 

Und Verriegelung wird durch die Klasse locking "selbst" ausgeführt:

void MyClass::Method() 
{ 
    Lock lock(this); 
    // ... 
} 

es irgendwelche Vorteile oder Nachteile dieses Ansatzes? Oder ist das nur ein Stilproblem?

+0

müssen Sie speziell auf den 'geerbten Mutex' Teil spezifischer sein. Wurde es von einer Schnittstelle oder einem echten Synchronisationsobjekt geerbt? – YeenFei

+0

@YeenFei - es wurde von einem realen (d.h. konkreten) Synchronisationsobjekt geerbt. – LeopardSkinPillBoxHat

Antwort

4

Privat Erbe könnte ein wenig mehr Sinn dafür machen, da private Vererbung mehr oder weniger eine Art und Weise Zusammensetzung zu implementieren ist. Wenn ich jedoch nicht von Mutex erben müsste (wie wenn Mutex geschützte Mitglieder hätten, auf die zugegriffen werden müsste), denke ich, dass der Standardzusammensetzungsansatz, ihn zu einem Mitglied zu machen, wahrscheinlich weniger Verwirrung verursachen würde verwendet statt Mutex ein Mitglied zu machen).

Eine Situation, in der es sinnvoll sein könnte, öffentlich zu erben, ist, wo Clients aus bestimmten Gründen in der Lage sein sollen, das Objekt zu sperren, dann können sie einfach MyClass als Mutex behandeln. Das ist vielleicht keine großartige Design-Wahl, da Sie mehr Möglichkeiten für Deadlocks eröffnen, wenn das Objekt auf unerwartete Weise gesperrt wurde. Wenn die Mutex privat bleibt (ob durch Vererbung oder durch Standardzusammensetzung), kann die Klasse sicherer sein, wie genau die Sperre verwendet wird.

Ich wäre nicht überrascht, wenn die Person, die dieses Design eingeführt hat, von .NET beeinflusst wurde, wo ein Objekt "abschließbar" ist. Beachten Sie, dass es in .NET früher üblich war, zu sein, aber dieses Idiom ist in Ungnade gefallen, und jetzt wird es als korrekter angesehen, ein bestimmtes privates Objektelement zum Sperren zu verwenden.

6

Das macht fast nie Sinn. Ist MyClass eine Art von Synchronisierungsobjekt, das Mutex erweitert? Wenn nicht, dann ist Vererbung mit ziemlicher Sicherheit die falsche Wahl, weil es keinen Sinn macht, MyClass als Mutex zu verwenden (die Beziehung MyClass zu Mutex ist keine "ist-a" -Beziehung).

Es ist auch gefährlich:

MyClass x; 
Lock lock(x); 
x.Method(); // uh oh. 
+0

Beachten Sie, dass ein Thread in der Win32-Welt mehrfach gesperrt werden kann, also gibt es kein "uh oh". Dies scheint ein vernünftiger Ansatz für Sperren zu sein, aber das könnte daran liegen, dass ich das gewohnt bin. –

+2

@Michael: Einige Plattformen/Thread-Bibliotheken haben sowohl einen "Mutex" als auch einen "RecursiveMutex" und wenn ein Thread einen Mutex ein zweites Mal gesperrt hat, würde er sich selbst blockieren. Ich habe keine Ahnung, ob das ein gemeinsamer Ansatz ist. –