簡體   English   中英

每個線程的局部靜態變量

[英]Local static variables for each thread

假設我有一個類,在初始化之后創建一個線程並在其中運行一個方法,在其中聲明一個靜態變量:

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

如果我創建了更多類的對象,例如3,那么該方法將在3個不同的線程中被調用3次。 之后var將等於3.如何完成功能,其中每個線程都有自己的靜態var ,獨立於其他線程。 我將非常感謝所有的幫助。

您可以使用thread_local關鍵字指示對象具有線程存儲持續時間。 你可以像這樣使用它:

static thread_local int V;

如果需要有關存儲類說明符的更多信息,可以查看CppReference

這就是thread_local存儲類說明符的用途:

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

這意味着每個線程都有自己的var版本,它將在第一次運行該函數時初始化,並在線程退出時銷毀。

你在評論中說:

我確實想要一個特定於每個類實例的變量

這正是實例變量(也就是每個實例成員)。

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

好吧,如果你想要一個變量與線程不同,那么該變量不應該是靜態的。 它失去了一個靜態變量的點,根據定義,它是一個變量:

  1. 它由該類的所有對象共享。
  2. 它不需要訪問類實例(對象)。

你問的問題不是“編碼問題”,而是建築問題。 我不知道你正在開發什么樣的系統/應用程序,也許你需要以不同的方式處理你的問題。

問自己這個問題:

  • 為什么我需要線程?
  • 為什么我需要這個變量是靜態的?
  • 我需要在線程之間共享哪些信息以及我不想分享哪些信息?

如果你更具體,也許我可以給你一個更具體的答案/方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM