通过继承而不是组合来锁定

发布于 2024-10-07 14:15:42 字数 503 浏览 8 评论 0原文

在我编写或审阅的大多数代码中,锁定是通过组合实现的,其中类拥有关键部分或互斥锁:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冬天旳寂寞 2024-10-14 14:15:42

这几乎没有任何意义。 MyClass 是某种扩展 Mutex 的同步对象吗?如果不是,那么继承几乎肯定是错误的选择,因为使用 MyClass 作为 Mutex 是没有意义的(MyClass 的关系)到 Mutex 不是“is-a”关系)。

这也很危险:

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

This almost never makes sense. Is MyClass some kind of synchronization object that extends Mutex? If not, then inheritance is almost certainly the wrong choice because it doesn't make sense to use MyClass as a Mutex (the relationship of MyClass to Mutex is not an "is-a" relationship).

It's also dangerous:

MyClass x;
Lock lock(x);
x.Method();   // uh oh.
掩饰不了的爱 2024-10-14 14:15:42

私有继承可能对此更有意义,因为私有继承或多或少是实现组合的一种方式。但是,除非需要从 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 if Mutex 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 making Mutex 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 a Mutex. 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 the Mutex 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文