C++ Meyers Singleton - 线程安全(代码等效于互斥锁?)

标签 c++ thread-safety singleton static-methods static-members

上周有人指出我有一段代码是这样的:

#include <pthread.h>
namespace NSTest
{
class SingletonClass
{
public:


    static SingletonClass & getInstance()
    {
        static  pthread_mutex_t mutex;
        pthread_mutex_lock(&mutex);
        if(singletonPtr==nullptr)
        {
            createInstence();
        }
        return (*singletonPtr);
        pthread_mutex_unlock(&mutex);

    }

private:
    static void createInstence()
    {
        static SingletonClass static_SingletonClass;
        singletonPtr=&static_SingletonClass;

    }
    static SingletonClass * singletonPtr;

};

SingletonClass * SingletonClass::singletonPtr=nullptr;


class SingletonClassNoStatic
{
public:
    static SingletonClassNoStatic & getInstance()
    {
        pthread_mutex_lock(&mutex);
        if(singletonPtr==nullptr)
        {
            createInstence();
        }
        return (*singletonPtr);
        pthread_mutex_unlock(&mutex);
    }
private:
    static void createInstence()
    {
        static SingletonClassNoStatic static_SingletonClass;
        singletonPtr=&static_SingletonClass;

    }
    static SingletonClassNoStatic * singletonPtr;

    static  pthread_mutex_t mutex;
};
SingletonClassNoStatic * SingletonClassNoStatic::singletonPtr=nullptr;
pthread_mutex_t SingletonClassNoStatic::mutex;
}
int main()
{

    NSTest::SingletonClass::getInstance();
    NSTest::SingletonClassNoStatic::getInstance();

    return 0;
}

方法 getInstance 被指出是正确的方法,原始方法是 getIntance(StaticMutex),编码不是线程安全的 (c++98) 因为互斥锁是在方法中创建的,它是静态的并且对于静态互斥锁,我遵循静态方法中的静态实例的规则创建一次并且不再创建,但是这条规则因为不适用于互斥锁。我有疑问,修正可以吗?访问该方法(静态互斥体)的每个线程都将创建自己的互斥体?我在读到该操作仅适用于来自类的方法,但由于互斥量是在静态方法中静态创建的,因此它将被创建一次。 我是否正确理解了这个概念?

最佳答案

在 C++11 中(由 std::mutex 隐含)整个 Meyers 单例用两行表示:

Singleton& instance() {
  static Singleton instance;

  return instance;
}

不需要其他任何东西。问题本身非常不清楚,因为您在同一上下文中谈论 C++98 和 std::mutex,而这些并没有加起来。

已发布代码的另一个问题是它不是开始时是迈耶的单例。

关于C++ Meyers Singleton - 线程安全(代码等效于互斥锁?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34001420/

相关文章:

c++ - 从 VS2008 迁移到 VS2010 时要记住的事情

c++ - C++11 内存模型是否可以防止内存撕裂和冲突?

java - 当等待 Vector 对象的线程大于 6 时,wait 和 notificationAll 机制无法按预期工作

jsf - Java单例类与JSF应用程序范围的托管bean - 区别?

node.js - 对 Node.js 模块使用单例方法

java - REST 端点 - Singleton 与 RequestScoped

c++ - 如何使用一个 makefile 构建可执行文件的变体?

c++ - 结构体构造函数中不允许使用不完整类型

c++ - 如何在类(class)学生的枚举中添加和删除值

C++ 线程安全 vector .erase