multithreading - C++11 const - 我的代码是线程安全的吗?

标签 multithreading c++11 thread-safety constants

我有以下类(class):

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;
};

由于 get_object_name 是一个昂贵的函数,我想进行一种延迟初始化,并且仅在第一次 get_name() 时调用它叫。如果它从未被调用,那么我不会浪费资源来获取名称。

我担心第一次调用 _name.empty()。我当前的代码是否保证是线程安全的,或者我是否需要将锁移至函数的顶部?

我观看了 Herb Sutter 的一些演讲,特别是 this one ,这张幻灯片出现的地方:

http://i.imgur.com/Jz4luYe.png

这让我相信对 empty() 的调用是线程安全的。但我的变量(_name)是可变的。 “const == 线程安全”规则在这里仍然适用吗?

get_name() 是唯一可以修改 _name 的函数。

最佳答案

不,它不是线程安全的,因为您(读取)在 mutex 之外访问 _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;
};

这保证 get_object_name() 不会被多次调用。第一次调用将初始化字符串,并发调用将阻塞,直到 lambda 完成。
同步得到了充分处理,这意味着任何获取字符串引用的线程都可以安全地从中读取。

关于multithreading - C++11 const - 我的代码是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44527103/

相关文章:

c# - 多次调用和线程安全

c# - C#计时器2同时执行的 Action

c++ - 它怎么可能成为竞争条件。或者我的代码有问题

c# - 线程和线程启动

c++ - 如何检查所有可变参数模板参数是否具有特殊功能?

multithreading - 什么时候要注意EJB中的多线程?

c# - 调用Invoke挂起程序

c++ - 在旧版本的 linux 上运行我的代码

c++ - 如何用 NaN 元素初始化双矩阵?

C++ 模板 - 广义操作和实例之间成员的可见性