简体   繁体   中英

Local static variables for each thread

Lets say I have a class that after initialization creates a thread and runs a method in it, within it declares a static variable:

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

If I create more objects of the class, for example 3, then the method will be called 3 times in 3 different threads. After that var will equal 3. How to accomplish the functionality, where each thread has its own static var that is independent of others. I would appreciate all help.

You can use the thread_local keyword which indicates that the object has a thread storage duration. You can use it like that :

static thread_local int V;

If you want more information about storage class specifiers, you can check CppReference .

This is what the thread_local storage class specifier is for:

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

This means that each thread will have its own version of var which will be initialized on the first run through that function and destroyed on thread exit.

You said, in a comment:

I do want a variable that is specific for each instance of a class

That's precisely what an instance variable is (aka a per-instance member).

static members and function local variables are not specific to each instance of a class! They are either completely global (one instance per entire executable), or are per-thread if you use C++11 and declare them thread_local .

You absolutely need a member variable. That's the only way to guarantee that the variable will be specific for each instance of the class.

You might argue that you create a dedicated thread per each instance of the class. First of all, it's likely that you shouldn't be doing that. Secondly, if you ever change your mind, and stop creating a per-class thread and, say, use a thread pool instead, your code will instantly break.

So, the proper and straightforward thing is to have it as an instance variable (as opposed to a class variable):

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

If you want, you can indicate your intent by including the method's name in the variable name:

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

Finally, if you're OK with a bit more typing, you can use a member wrapper to enforce the scope it's used in:

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

Well, if you want a variable to be different from thread to thread, that variable should not be static. It's looses the point of a static variable, which is, by definition, a variable that:

  1. It's shared by all objects of that class.
  2. It does not need an class instance (object) to be accessed.

The question you're asking it's not a "coding problem", but an architectural one. I don't know what kind of system/app you're developing, maybe you need to approach your problem in a different way.

Ask yourself this questions:

  • Why do I need threads?
  • Why do I need this variable to be static?
  • What information do I need to share between threads and what information I don't want to share?

If you are more specific, maybe I can give you a more specific answer/approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM