简体   繁体   English

线程安全单例课程-我这样做正确吗?

[英]Thread Safe Singleton Class - Am I doing this Right?

I am creating a system state class that needs be thread safe in reading/writing. 我正在创建一个系统状态类,该类在读取/写入时需要线程安全。 I am implementing it using the Singleton Design Pattern. 我正在使用Singleton设计模式来实现它。 I have based it off of pointers from these Stackoverflow questions: 我基于这些Stackoverflow问题的指针:

  1. Singleton: How it Should be Used Singleton:应如何使用
  2. C++ Singleton Design Pattern C ++单例设计模式

Here is a condensed example of my code. 这是我的代码的精简示例。 Essentially it is just some state variables I need to keep track of and share across several threads. 本质上,这只是我需要跟踪并在多个线程之间共享的一些状态变量。 I know for a fact there will only ever needs be one state instance and I know that it needs to thread safe and constant. 我知道一个事实,那就是永远只需要一个状态实例,而且我知道它需要安全且恒定地线程化。 Will this implementation ensure that? 这样的实施能确保吗?

// System_State.h
class System_State
{
public:
    static System_State &getInstance()
    {
        static System_State stateInstance;
        return stateInstance;
    }

    System_State(System_State const&)   = delete;
    void operator=(System_State const&) = delete;

    // Example Setter with mutex guard
    void setWifiConnectedStatus(uint8_t _status)
    {
        std::lock_guard<std::mutex> lock(mtx);
        Wifi.ConnectedStatus = _status;
    }

private:
    System_State() 
    {
        initializeState();
    }

    void initializeState();

    std::mutex mtx;

    static struct WifiService
    {
        uint8_t     ConnectedStatus;
        std::string CurrentConnection;
        std::string SavedNetworks;
        std::string AvailableNetworks;
        std::string ForgetNetwork;
        std::string ConnectTo;
        std::string DisconnectFrom;
    } Wifi;

    static struct ScanService
    {
        std::string PerformScan;
        std::string ScanStatus;
        uint8_t     ScanProgress;
    } Scan;

    static struct UploadDataService
    {
        std::string PerformUpload;
        uint8_t     UploadProgress;
        uint8_t     ItemsWaitingToBeUploaded;
    } UploadData;

    static std::string LEDControlBrightness;
    static uint8_t     BatteryPercentage;
};

And here is some example main 这是一些主要的例子

//main.cpp
#include <thread>

void loop1()
{
    System_State state = System_State::getInstance();
    while(true)
    {
        //do randomness with state
    }
}

void loop2()
{
    System_State state2 = System_State::getInstance();
    while(true)
    {
        //do randomness with state2
    }
}

int main()
{
    std::thread t1(loop1);
    std::thread t2(loop2);
    // do and join and all that!
    return 0;
}

Yours is not idiomatic singleton, because it is still prone to so-called "static initialization order fiasco". 您的不是惯用的单例,因为它仍然容易发生所谓的“静态初始化顺序惨败”。

An idiomatic singleton doesn't have a static class member, instead it's instance function looks like 惯用的单例没有静态类成员,而是其实例函数看起来像

static MySingleton& instance() {
    static MySingleton the_ton;
    return the_ton;
}

More on the fiasco: static initialization order fiasco 关于惨败的更多信息: 静态初始化顺序惨败

No, this may not work in a more complex case, but not for thread-safety reason, but because of the undefined behavior of static object initialization. 不,这可能在更复杂的情况下不起作用,但不是出于线程安全的原因,而是由于静态对象初始化的不确定行为。

Let's say that your object here: 假设您的对象在这里:

static System_State stateInstance;

requires another static object that you retrieve with another static getInstance . 需要使用另一个静态getInstance检索的另一个静态对象。 You have no assurance that this will return a valid/constructed object. 您不能保证这将返回有效/构造的对象。

If you can ensure that this object doesn't require another static object, then you should be fine. 如果可以确保该对象不需要其他静态对象,则应该可以。 But this is the issue with lots of singleton constructions, you have to balance when it is constructed and thread-safety. 但这是许多单例构造的问题,在构造构造和线程安全性时必须兼顾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM