3

在我编写或查看的大多数代码中,锁定是通过组合实现的,其中一个类拥有一个临界区或互斥锁:

class MyClass
{
    Mutex mMutex;
};

当可以通过多个线程访问可变成员时,我们通过 RAII 获取和释放锁,如下所示:

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

今天我回顾了一些通过继承实现锁定的代码,如下所示:

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

并且锁定由类锁定“本身”执行:

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

这种方法有什么优点或缺点吗?或者这只是一个风格问题?

4

2 回答 2

6

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

这也很危险:

MyClass x;
Lock lock(x);
x.Method();   // uh oh.
于 2010-12-13T01:00:41.247 回答
4

私有继承可能对此更有意义,因为私有继承或多或少是一种实现组合的方式。但是,除非需要继承自Mutex(例如,如果Mutex有需要访问的受保护成员),我认为将其作为成员的更标准的组合方法可能会减少混乱(就像人们想知道为什么要使用继承成为Mutex会员)。

公开继承可能有意义的一种情况是,您希望客户端能够出于某种原因锁定该对象,然后他们可以简单地将MyClass其视为Mutex. 这可能不是一个很好的设计选择,因为如果对象以意想不到的方式锁定,您会打开更多的死锁机会。如果Mutex保持私有(无论是通过继承还是通过标准组合),该类可以更确切地确定锁的使用方式。

如果介绍这种设计的人受到任何对象都是“可锁定”的 .NET 的影响,我不会感到惊讶。请注意,在 .NET 中,它曾经很常见lock(this),但该习惯用法已不受欢迎,现在认为使用特定的私有对象成员用于锁定更为正确。

于 2010-12-13T01:22:53.787 回答