2010-12-13 70 views
3

Dans la plupart des codes je l'ai écrit ou révisé, le verrouillage est réalisée par composition, où une classe possède une section critique ou mutex:verrouillage par héritage plutôt que la composition

class MyClass 
{ 
    Mutex mMutex; 
}; 

et lorsque les membres mutables peuvent potentiellement être accessible via plusieurs threads, nous acquérons et libérer le verrou par RAII comme ceci:

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

Aujourd'hui, je passé en revue un code où le code a mis en œuvre le verrouillage par héritage, comme ceci:

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

Et verrouillage est effectué par le verrouillage de classe « lui-même »:

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

Y a-t-il des avantages ou des inconvénients de cette approche? Ou est-ce juste un problème de style?

+0

vous devrez être plus précis, en particulier sur la partie «mutex héritée». A-t-il été hérité d'une interface ou d'un objet de synchronisation réel? – YeenFei

+0

@YeenFei - il a été hérité d'un objet de synchronisation réel (c'est-à-dire concret). – LeopardSkinPillBoxHat

Répondre

4

héritage privé pourrait faire un peu plus de sens pour cela, puisque l'héritage privé est plus ou moins un moyen de mettre en œuvre la composition. cependant, sauf si vous avez besoin d'hériter de Mutex (comme si Mutex avait des membres protégés auxquels il fallait accéder), je pense que l'approche de composition plus standard pour en faire un membre causerait probablement moins de confusion (comme les gens se demandent pourquoi l'héritage était utilisé au lieu de faire Mutex un membre). Une situation où il peut être logique d'hériter publiquement est l'endroit où vous voulez que les clients puissent verrouiller sur cet objet pour une raison quelconque, alors ils peuvent simplement traiter MyClass comme Mutex. Ce n'est peut-être pas un bon choix de conception, puisque vous ouvrez plus de possibilités d'interblocage si l'objet a été verrouillé de manière imprévue. Si le Mutex reste privé (que ce soit par héritage ou par composition standard), la classe peut être plus sûr de la façon dont le verrou est utilisé.

Je ne serais pas surpris si la personne qui a introduit cette conception a été influencée par .NET où tout objet est 'verrouillable'. Notez que dans .NET, il était commun à lock(this), mais cet idiome est tombé en défaveur, et maintenant il est considéré plus correct d'avoir un membre d'objet privé spécifique à utiliser pour le verrouillage.

6

Ceci n'a presque jamais de sens. MyClass est une sorte d'objet de synchronisation qui s'étend Mutex? Si ce n'est pas le cas, alors l'héritage est presque certainement le mauvais choix car cela n'a aucun sens d'utiliser MyClass comme Mutex (la relation de MyClass à Mutex n'est pas une relation "est-un").

Il est aussi dangereux:

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

Notez que dans le monde Win32, un thread peut prendre un verrou plusieurs fois, donc il n'y a pas de "oh oh". Cela semble être une approche raisonnable pour les verrous, mais c'est peut-être parce que c'est ce à quoi je suis habitué. –

+2

@Michael: Certaines plates-formes/bibliothèques de threads ont à la fois un "Mutex" et un "RecursiveMutex" et si un thread bloquait un Mutex une seconde fois, il se bloquerait avec lui-même. Je n'ai aucune idée si c'est une approche commune. –