通过继承而不是组合来锁定
在我编写或审阅的大多数代码中,锁定是通过组合实现的,其中类拥有关键部分或互斥锁:
class MyClass
{
Mutex mMutex;
};
当可变成员可能通过多个线程访问时,我们获取并释放锁像这样通过 RAII:
void MyClass::Method()
{
Lock lock(mMutex);
// ...
}
今天我回顾了一些代码,其中代码通过继承实现锁定,如下所示:
class MyClass : public Mutex
{
// ...
};
锁定是由类锁定“本身”执行的:
void MyClass::Method()
{
Lock lock(this);
// ...
}
这种方法有什么优点或缺点?或者这只是一个风格问题?
In most code I have written or reviewed, locking is achieved via composition, where a class owns a critical section or mutex:
class MyClass
{
Mutex mMutex;
};
and when mutable members can potentially be accessed via multiple threads, we acquire and release the lock via RAII like this:
void MyClass::Method()
{
Lock lock(mMutex);
// ...
}
Today I reviewed some code where the code was implementing locking via inheritance, like this:
class MyClass : public Mutex
{
// ...
};
And locking is performed by the class locking "itself":
void MyClass::Method()
{
Lock lock(this);
// ...
}
Are there any advantages or disadvantages of this approach? Or is this just a style issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这几乎没有任何意义。
MyClass
是某种扩展Mutex
的同步对象吗?如果不是,那么继承几乎肯定是错误的选择,因为使用MyClass
作为Mutex
是没有意义的(MyClass
的关系)到Mutex
不是“is-a”关系)。这也很危险:
This almost never makes sense. Is
MyClass
some kind of synchronization object that extendsMutex
? If not, then inheritance is almost certainly the wrong choice because it doesn't make sense to useMyClass
as aMutex
(the relationship ofMyClass
toMutex
is not an "is-a" relationship).It's also dangerous:
私有继承可能对此更有意义,因为私有继承或多或少是实现组合的一种方式。但是,除非需要从
Mutex
继承(就像Mutex
有需要访问的受保护成员),我认为更标准的组合方法成员可能会引起更少的混乱(就像人们想知道为什么使用继承而不是使Mutex
成为成员一样)。公开继承可能有意义的一种情况是,您希望客户端能够出于某种原因锁定该对象,然后他们可以简单地将
MyClass
视为Mutex
。这可能不是一个很好的设计选择,因为如果对象以意外的方式锁定,就会有更多的死锁机会。如果互斥锁保持私有(无论是通过继承还是通过标准组合),则类可以更确定锁的具体使用方式。如果引入此设计的人受到 .NET 的影响(其中任何对象都是“可锁定的”),我不会感到惊讶。请注意,在 .NET 中,
lock(this)
曾经很常见,但这种习惯用法已不再受欢迎,现在认为使用特定的私有对象成员来进行锁定更为正确。Private inheritance might make a little more sense for this, since private inheritance is more or less a way to implement composition. however, I unless there's a need to inherit from
Mutex
(like ifMutex
had protected members that needed to be accessed), I think that the more standard composition approach of making it a member would probably cause less confusion (like people wondering why inheritance was used instead of makingMutex
a member).One situation where it might make sense to inherit publicly is where you want clients to be able to lock on that object for some reason, then they can simply treat
MyClass
as aMutex
. That might not be a great design choice, since you open up more opportunities for deadlock if the object were locked in unanticipated ways. If theMutex
remains private (whether by inheritance or by standard composition) the class can be more certain of exactly how the lock is used.I wouldn't be surprised if the person who introduced this design was influenced by .NET where any object is 'lockable'. Note that in .NET it used to be common to
lock(this)
, but that idiom has fallen into disfavor, and now it's considered more correct to have a specific private object member to use for locking.