每个线程的局部静态变量

时间:2015-07-24 11:16:50

标签: c++ multithreading c++11 static

假设我有一个类,在初始化后创建一个线程并在其中运行一个方法,在其中声明一个静态变量:

void method()
{
     static int var = 0;
     var++;
}

如果我创建了更多类的对象,例如3,那么该方法将在3个不同的线程中被调用3次。之后var将等于3。 如何完成功能,其中每个线程都有自己的静态var,独立于其他线程。我将非常感谢你的帮助。

4 个答案:

答案 0 :(得分:33)

您可以使用thread_local关键字指示对象具有线程存储持续时间。您可以这样使用它:

static thread_local int V;

如果您想了解有关存储类说明符的更多信息,可以查看CppReference

答案 1 :(得分:13)

这是thread_local存储类说明符的用途:

void method()
{
     thread_local int var = 0;
     var++;
}

这意味着每个线程都有自己的var版本,它将在第一次运行该函数时初始化,并在线程退出时销毁。

答案 2 :(得分:7)

你在评论中说:

  

我确实想要一个特定于类

的每个实例的变量

这正是一个实例变量(例如,每个实例成员)。

static成员和函数局部变量特定于每个类的实例!它们要么是完全全局的(每个可执行文件一个实例),要么是每个线程,如果你使用C ++ 11并声明它们thread_local

你绝对需要一个成员变量。这是保证变量特定于每个类实例的唯一方法。

您可能会争辩说,您为每个类的实例创建一个专用线程。首先,你可能不应该这样做。其次,如果你改变主意,并停止创建每个类的线程,比如使用线程池,你的代码将立即中断。

因此,正确和直接的事情是将它作为实例变量(而不是类变量):

// OK - instance variable
class C { int var; };

// WRONG - class variable and lookalikes
class C { static int var; };
class C { void foo() { static int var; } };

// WRONG - thread variable, but **not** instance variable
class C { static thread_local int var; };
class C { void foo() { static thread_local int var; } };

如果需要,可以通过在变量名称中包含方法名称来表明您的意图:

class C {
  int foo_var;
  C() : foo_var(0) {}
  void foo() { ... }
};

最后,如果您可以更多地输入,可以使用成员包装器来强制执行它所使用的范围:

#include <utility>
#include <cassert>

template <typename T, typename Member, Member member>
class ScopedMember {
   T data;
public:
   explicit ScopedMember(const T & d) : data(d) {}
   explicit ScopedMember(T && d) : data(std::move(d)) {}
   ScopedMember() {}
   template <Member m, void(*)(char[member == m ? 1 : -1]) = (void(*)(char[1]))0>
   T & use() { return data; }
   template <Member m, void(*)(char[member == m ? 1 : -1]) = (void(*)(char[1]))0>
   const T & use() const { return data; }
};

class C {
public:
   C() : m_foo(-1) {}
   void granted() {
      auto & foo = m_foo.use<&C::granted>();
      foo = 5;
      assert(m_foo.use<&C::granted>() == 5);
   }
   void rejected() {
#if 0
      // Won't compile
      auto & foo = m_foo.use<&C::rejected>();
#endif
   }
private:
   ScopedMember<int, void(C::*)(), &C::granted> m_foo;
};

int main()
{
   C().granted();
   return 0;
}

答案 3 :(得分:-2)

好吧,如果你想要一个变量与线程不同,那么该变量不应该是静态的。它失去了一个静态变量的点,根据定义,它是一个变量:

  1. 该类的所有对象共享。
  2. 不需要访问类实例(对象)。
  3. 你问的问题不是编码问题&#34;而是建筑问题。我不知道你正在开发什么样的系统/应用程序,也许你需要以不同的方式处理你的问题。

    问自己这个问题:

    • 为什么我需要线程?
    • 为什么我需要这个变量是静态的?
    • 我需要在线程之间分享哪些信息以及我不想分享哪些信息?

    如果你更具体,也许我可以给你一个更具体的答案/方法。

相关问题