use*_*119 4 c++ multithreading mutex c++11
据我了解,C++ 11 具有静态线程安全性。这意味着获取/创建单例的实例没有问题。这是因为静态现在是线程安全的,并且在多线程环境中不会引起任何问题。然而,问题是我是否需要一个互斥体来访问单例中的数据字段。真的和单例有关系吗?在多线程环境中访问数据字段时,即使模式不是单例,是否也需要互斥锁。这是完整的代码。
class Singleton
{
private:
Singleton()
{
std::cout<<"Singleton Initialized"<<std::endl;
}
Singleton(Singleton const&)
{
std::cout<<"Singleton copy constructor not allowed"<<std::endl;
}
Singleton& operator=(Singleton const&)
{
std::cout<<"Singleton Assignment Operator not allowed"<<std::endl;
}
~Singleton()
{
std::cout<<"Singleton Destructor not allowed"<<std::endl;
}
int m_data;
public:
int getData()
{
return m_data;
}
void setData(int data)
{
m_data = data;
}
static Singleton * instance( )
{
static Singleton *single_manager = new Singleton();
return single_manager;
}
};
Run Code Online (Sandbox Code Playgroud)
长话短说:博士:是的。
C++ 11“静态线程安全”可防止以下情况中的竞争条件:
static Singleton *single_manager = new Singleton();
Run Code Online (Sandbox Code Playgroud)
如果没有这个,可能的问题是:
但是,当从不同线程调用它们时,对m_data(即GetData和)的任何访问都需要互斥体。SetData
在哪里锁定- 单例内部应该有锁,还是调用者应该锁?
(根据评论)
这个问题没有简单的答案。
我会向单例类添加一个锁,并在 GetData / SetData 中锁定。理由:这几乎总是默认用例,并减轻了调用者的负担。
但是:
内部锁并不总是足够的,例如,如果您有:
Singleton * s = Singleton::instance();
int x = s->GetData();
x = x + 1;
s->SetData(x);
Run Code Online (Sandbox Code Playgroud)
调用者需要在 Get/Modify/Set 周围使用外部锁。
反对内锁的论据如下:
结论: 如果您可以避免手头数据的 get-modify-set 场景,那么添加内部锁(例如 API 可以包含 )IncrementData方法似乎是明智的做法。清楚地记录接口的线程安全性(例如“此类不是线程安全的,需要外部锁定”或“单个函数调用是线程安全的”)
笔记:
是的:正如您已经想到的:这与该类是单例无关。
如果数据实际上只是一个 int,则可以使用“原子整数”(例如来自 boost:.atomic)。不过,获取/设置/修改问题仍然存在。