在我的 C++ 项目中,我有一个单例类。在项目执行期间,有时会同时从两个不同的线程访问同一个单例类。导致产生了两个单例类的实例,这是一个问题。
如何处理这种情况?
那么它就不是单例了:-)
您可能需要向我们展示一些代码,但您的基本问题将与同步区域有关。
如果做得好,两个线程就不可能创建类的两个对象。事实上,类本身应该是强制执行单例性质的地方,这样错误的客户端就不会破坏意图。
基本结构将是:
lock mutex
if instance doesn't exist:
instance = new object
unlock mutex
如果没有诸如互斥锁保护之类的东西(或关键代码部分或您可以在语言/库级别保证两个线程不能同时运行代码的任何其他方式),则线程一个可能会在检查之间被换出和实例化,导致您的“单例”的两个可能实例。
而且,正如其他人无疑会建议的那样,单身很可能是个坏主意。我并不完全处于每次使用都是错误的阵营中,通常的问题是人们将它们视为“上帝”对象。它们可以有它们的用途,但通常有更好的方法,尽管我不会假设告诉你你需要改变它,因为我不知道你的用例。
如果您在不同的线程中获得两个不同的实例,那么您做错了。与进程不同,线程共享它们的内存。因此,在一个线程中分配的内存(例如,用于对象实例)也可以在另一个线程中使用。
如果您的单身人士获得两份副本,则不受互斥锁的保护。在获取/访问/设置内部对象时锁定互斥锁。
我相信您已经完成了这样的事情,if(!_instance)_instance = new Singleton()
其中有一个关键部分。您需要使用互斥锁来保护它。
不要使用单例,这是众所周知的反模式。
一本好书:
单身人士:解决自 1995 年以来从未遇到过的问题
如果您出于只有您自己知道的原因仍想坚持并继续使用它,您需要的是一个线程安全的单例实现,如下所示:
YourClass* YourClass::getInstance()
{
MutexLocker locker(YourClass::m_mutex);
if(!m_instanceFlag)
{
m_instance = new YourClass();
m_instanceFlag = true;
}
return m_instance;
}
MutexLocker
通常使用的互斥锁的包装类在哪里,它在创建其实例时锁定互斥锁并解锁函数结束的互斥锁。