在将单例类重构为线程安全(fallowing Herb Sutter advice how to write proper double-check locking)的过程中,我遇到了支持原子但不支持nullptr的编译器版本(带有--std = c++ 0x标志的gcc 4.4.7)问题。
当前代码
class SingletonClass {
public:
SingletonClass* getInstance() {
if (instance == NULL) {
instance == new SingletonClass();
}
return instance;
}
private:
SingletonClass() = default;
~SingletonClass() = default;
static SingletonClass* instance;};
我想达到的目标
#include <cstdatomic>
#include <mutex>
class SingletonClass {
public:
SingletonClass* getInstance() {
if (instance == NULL) {
std::lock_guard<std::mutex> lock (m);
if(instance == NULL){
instance = new SingletonClass();
}
}
return instance;
}
private:
SingletonClass() = default;
~SingletonClass() = default;
static std::atomic<SingletonClass*> instance;
static std::mutex m;
};
但这给了我一个错误,说没有运算符可以将原子ptr编译为NULL
main.cpp: In member function ‘SingletonClass* SingletonClass::getInstance()’:
main.cpp:7: error: ambiguous overload for ‘operator==’ in ‘SingletonClass::instance == 0l’
main.cpp:7: note: candidates are: operator==(void*, void*) <built-in>
main.cpp:7: note: operator==(SingletonClass*, SingletonClass*) <built-in>
由于我不能将实例ptr强制为NULL或不能使用nullptr来解决它,并检查其是否已初始化?
最佳答案
您可以使用将指针隐式转换为bool的方法:
SingletonClass* getInstance() {
if (instance.load()) {
std::lock_guard<std::mutex> lock (m);
if(instance.load()){
instance.store(new SingletonClass());
}
}
return instance;
}
See it online
请注意,从
std::atomic<SingletonClass*>
到SingletonClass*
的隐式转换是可能的,但是在这种情况下是模棱两可的。另外,分配本身是模棱两可的,因此添加了store()
调用。但是,也许解决方案更简单-为什么您完全需要
std::atomic
?您已经锁定了对存储指针的访问,因此很安全:#include <mutex>
class SingletonClass {
public:
SingletonClass* getInstance() {
std::lock_guard<std::mutex> lock (m);
if (instance == NULL) {
instance = new SingletonClass();
}
return instance;
}
private:
SingletonClass() = default;
~SingletonClass() = default;
static SingletonClass* instance;
static std::mutex m;
};
std::atomic
用于无锁访问(或至少“隐藏锁”访问)。我想不出同时使用两者的理由。这里非常需要Mutex-您想将整个功能锁定为关键部分,否则两个线程可能会创建两个单例对象,而一个则会泄漏。
关于c++ - 检查在gcc 4.4.7中没有初始化whter atomic ptr(无nullptr),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60620742/