Multithreading C++;11 const-我的代码线程安全吗?
我有以下课程:Multithreading C++;11 const-我的代码线程安全吗?,multithreading,c++11,thread-safety,constants,Multithreading,C++11,Thread Safety,Constants,我有以下课程: class Object { public: Object() {} const std::string& get_name() const { if(_name.empty()) { std::lock_guard<std::mutex> lock(_lock); // Check if its still empty. Some other thread might have gotten here fir
class Object
{
public:
Object() {}
const std::string& get_name() const
{
if(_name.empty()) {
std::lock_guard<std::mutex> lock(_lock);
// Check if its still empty. Some other thread might have gotten here first
if(_name.empty()) {
//Run expensive operation
_name = get_object_name();
}
}
return _name;
}
private:
std::string get_object_name(); // <- Expensive function
mutable std::mutex _lock;
mutable std::string _name;
};
类对象
{
公众:
对象(){}
常量std::string&get_name()常量
{
如果(_name.empty()){
标准:锁和防护锁(锁);
//检查它是否仍然是空的。其他线程可能先到达这里
如果(_name.empty()){
//经营昂贵的业务
_name=get_object_name();
}
}
返回_name;
}
私人:
std::string get_object_name();//否,它不是线程安全的,因为您(读取)在互斥体
之外访问\u name
,这会中断同步
一种可能的解决方案是使用标准库提供的std::call_once
机制
class Object
{
public:
Object() {}
const std::string& get_name() const
{
std::call_once(flag, [&] { _name = get_object_name(); });
return _name;
}
private:
std::string get_object_name() const; // <- Expensive function
mutable std::string _name;
mutable std::once_flag flag;
};
类对象
{
公众:
对象(){}
常量std::string&get_name()常量
{
std::call_once(标志,[&]{_name=get_object_name();});
返回_name;
}
私人:
std::string get_object_name()const;//启动C++11静态变量以线程安全的方式初始化。
如果获取名称的昂贵操作可以进行static
我认为以下操作更好:
class Object
{
public:
const std::string& get_name() const
{
static std::string name = expensive_get_name();
return name;
}
private:
static std::string expensive_get_name()
{
return "Name";
}
};
该模式有一个名称:。它在某些环境中有效,而在其他环境中无效。当它不起作用时,原因很微妙。是的,这正是我所担心的。您的一次呼叫
解决方案非常酷,但我喜欢它。我认为它的开销很小(如果我将其放入循环中,没有任何东西会使我的程序速度降低几个数量级),对吗?@标记call\u once的可能实现是双重检查锁定模式。开销(初始化后)可能相当于原子加载/获取,它相当于在X86
std::call_once(flag,[&]{u name=get_object_name();})上的常规加载
似乎更简短、更切题。一个只需调用一次并包含一行代码的方法似乎有点过分。注意:0在实践中,如果您违反此处的要求,简要说明会出现哪些问题可能是好的(特别是,指向字符串的指针可以在指向的内容到达CPU之前到达CPU,而无需同步。)@Yakk我喜欢lambda的建议,更改了itTBH,似乎get\u object\u name
只有一个函数,所以将其更改为set\u object\u name
(直接设置name
)甚至更短。这会导致所有对象具有相同的名称,这与它是一个const
(即非静态)方法这一事实不符。是的,正如@MSalters所说,这将导致所有对象实例具有相同的名称。第一次调用get_name()
将初始化该静态变量,它将用于对函数的所有其他调用,甚至用于其他对象。