0

在我的 C++ 项目中,我有一个单例类。在项目执行期间,有时会同时从两个不同的线程访问同一个单例类。导致产生了两个单例类的实例,这是一个问题。

如何处理这种情况?

4

4 回答 4

3

那么它就不是单例了:-)

您可能需要向我们展示一些代码,但您的基本问题将与同步区域有关。

如果做得好,两个线程就不可能创建类的两个对象。事实上,类本身应该是强制执行单例性质的地方,这样错误的客户端就不会破坏意图。

基本结构将是:

lock mutex
if instance doesn't exist:
    instance = new object
unlock mutex

如果没有诸如互斥锁保护之类的东西(或关键代码部分或您可以在语言/库级别保证两个线程不能同时运行代码的任何其他方式),则线程一个可能会在检查之间被换出和实例化,导致您的“单例”的两个可能实例。

而且,正如其他人无疑会建议的那样,单身很可能是个坏主意。我并不完全处于每次使用都是错误的阵营中,通常的问题是人们将它们视为“上帝”对象。它们可以有它们的用途,但通常有更好的方法,尽管我不会假设告诉你你需要改变它,因为我不知道你的用例。

于 2012-08-20T06:20:57.660 回答
1

如果您在不同的线程中获得两个不同的实例,那么您做错了。与进程不同,线程共享它们的内存。因此,在一个线程中分配的内存(例如,用于对象实例)也可以在另一个线程中使用。

于 2012-08-20T06:22:17.217 回答
1

如果您的单身人士获得两份副本,则不受互斥锁的保护。在获取/访问/设置内部对象时锁定互斥锁。

我相信您已经完成了这样的事情,if(!_instance)_instance = new Singleton()其中​​有一个关键部分。您需要使用互斥锁来保护它。

于 2012-08-20T06:23:14.837 回答
1

不要使用单例,这是众所周知的反模式
一本好书:
单身人士:解决自 1995 年以来从未遇到过的问题

如果您出于只有您自己知道的原因仍想坚持并继续使用它,您需要的是一个线程安全的单例实现,如下所示:

YourClass* YourClass::getInstance()
{
    MutexLocker locker(YourClass::m_mutex);
    if(!m_instanceFlag)
    {
        m_instance = new YourClass();
        m_instanceFlag = true;
    }
    return m_instance;
}

MutexLocker通常使用的互斥锁的包装类在哪里,它在创建其实例时锁定互斥锁并解锁函数结束的互斥锁。

于 2012-08-20T06:24:25.217 回答