单例模式 与 call_once

单例模式

单例模式,也叫单子模式,是一种常用的软件设计模式。 在应用这个模式时,单例对象的类必须保证只有一个实例存在。 许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。


懒汉式

不使用互斥

#include <iostream>
#include <thread>

using namespace std;

class Singelton
{
public:
    static Singelton* GetInstance();
    void FreeInstance();

private:
    Singelton(); // 使构造函数私有
    static Singelton* instance_;
};

Singelton* Singelton::instance_ = nullptr;

Singelton::Singelton()
{
    cout << "构造函数:" << this << endl;
}

Singelton* Singelton::GetInstance()
{
    // 没有锁,多线程下可能会多次实例化
    if (instance_ == nullptr)
        instance_ = new Singelton;
    return instance_;
}

void Singelton::FreeInstance()
{
    delete instance_;
    instance_ = nullptr;
}


#pragma region 测试单例类

void thread_func(int id)
{
    Singelton* instance = Singelton::GetInstance();
    cout << "线程" << id << "获得实例:" << instance << endl;
}

int main()
{
    thread t1(thread_func, 1);
    thread t2(thread_func, 2);
    t1.join();
    t2.join();

    cout << "运行结束" << endl;
}

#pragma endregion
Output
构造函数:01325468
线程1获得实例:01325468
构造函数:013316F0
线程2获得实例:013316F0
运行结束

使用互斥

#include <iostream>
#include <mutex>

using namespace std;

mutex singelton_mutex;

class Singelton
{
public:
    static Singelton* GetInstance();
    void FreeInstance();

private:
    Singelton(); // 使构造函数私有
    static Singelton* instance_;
};

Singelton* Singelton::instance_ = nullptr;

Singelton::Singelton()
{
    cout << "构造函数:" << this << endl;
}

Singelton* Singelton::GetInstance()
{
    if (instance_ == nullptr) // 双重锁定
    {
        lock_guard<mutex> lock(singelton_mutex);
        if (instance_ == nullptr)
            instance_ = new Singelton;
    }
    return instance_;
}

void Singelton::FreeInstance()
{
    delete instance_;
    instance_ = nullptr;
}


#pragma region 测试单例类

void thread_func(int id)
{
    Singelton* instance = Singelton::GetInstance();
    cout << "线程" << id << "获得实例:" << instance << endl;
}

int main()
{
    thread t1(thread_func, 1);
    thread t2(thread_func, 2);
    t1.join();
    t2.join();

    cout << "运行结束" << endl;
}

#pragma endregion
Output
构造函数:00CA53D0
线程1获得实例:00CA53D0
线程2获得实例:00CA53D0
运行结束


饿汉式

#include <iostream>
#include <thread>

using namespace std;

class Singelton
{
public:
    static Singelton* GetInstance();

private:
    Singelton(); // 使构造函数私有
    static Singelton* instance_;
};

Singelton* Singelton::instance_ = new Singelton;

Singelton::Singelton()
{
    cout << "构造函数:" << this << endl;
}

Singelton* Singelton::GetInstance()
{
    return instance_;
}


#pragma region 测试单例类

void thread_func(int id)
{
    Singelton* instance = Singelton::GetInstance();
    cout << "线程" << id << "获得实例:" << instance << endl;
}

int main()
{
    thread t1(thread_func, 1);
    thread t2(thread_func, 2);
    t1.join();
    t2.join();

    cout << "运行结束" << endl;
}

#pragma endregion
Output
构造函数:0134A090
线程1 获得实例:0134A090
线程2 获得实例:0134A090
运行结束

call_once 实现单例类

#include <iostream>
#include <mutex>

using namespace std;

std::once_flag singelton_once_flag;

class Singelton
{
public:
    static Singelton* GetInstance();
private:
    Singelton(); // 使构造函数私有
    static void CreateInstance();
    static Singelton* instance_;
};

Singelton* Singelton::instance_ = nullptr;

Singelton::Singelton()
{
    cout << "构造函数:" << this << endl;
}

void Singelton::CreateInstance()
{
    instance_ = new Singelton;
    cout << "创建实例:" << instance_ << endl;
}

Singelton* Singelton::GetInstance()
{
    // CreateInstance 只会执行一次
    std::call_once(singelton_once_flag, Singelton::CreateInstance);
    return instance_;
}


#pragma region 测试单例类

void thread_func(int id)
{
    Singelton* instance = Singelton::GetInstance();
    cout << "线程" << id << "获得实例:" << instance << endl;
}

int main()
{
    thread t1(thread_func, 1);
    thread t2(thread_func, 2);
    t1.join();
    t2.join();

    cout << "运行结束" << endl;
}

#pragma endregion
Output
构造函数:007D5468
创建实例:007D5468
线程2获得实例:007D5468
线程1获得实例:007D5468
运行结束
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。