我正在创建一个系统状态类,该类在读取/写入时必须是线程安全的。我正在使用Singleton设计模式来实现它。 我基于这些Stackoverflow问题的指针:
这是我的代码的精简示例。本质上,这只是我需要跟踪并在多个线程之间共享的一些状态变量。我知道一个事实,那就是永远只需要一个状态实例,而且我知道它需要安全且恒定地线程化。这种实施方式可以确保吗?
// 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;
};
这是一些主要示例
//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;
}
答案 0 :(得分:1)
您不是惯用的单例,因为它仍然容易发生所谓的“静态初始化顺序惨败”。
惯用单例没有静态类成员,而是其实例函数看起来像
static MySingleton& instance() {
static MySingleton the_ton;
return the_ton;
}
有关惨败的更多信息:static initialization order fiasco
答案 1 :(得分:0)
不,这可能在更复杂的情况下不起作用,但不是出于线程安全的原因,而是由于静态对象初始化的不确定行为。
假设您的对象在这里:
static System_State stateInstance;
需要使用另一个静态getInstance
检索的另一个静态对象。您无法保证这将返回有效/构造的对象。
如果可以确保该对象不需要其他静态对象,则应该没问题。但这是很多单例构造的问题,在构造构造和线程安全性时必须保持平衡。