簡體   English   中英

如何使用std :: atomic <>

[英]How to use std::atomic<>

我有一個類,我想在不同的線程中使用,我想我可以這樣使用std::atomic

class A
{
    int x;

public:
    A()
    {
        x=0;
    }

    void Add()
    {
        x++;
    }

    void Sub()
    {
        x--;
    }     
};

在我的代碼中:

  std::atomic<A> a;

並在另一個線程中:

  a.Add();

  a.Sub();

但我收到a.Add()未知的錯誤。 我怎么解決這個問題?

有沒有更好的方法來做到這一點?

請注意,這是一個示例,我想要的是確保對A類的訪問是線程安全的,所以我不能使用

std::atomic<int> x;

如何使用std::atomic創建一個類線程安全的?

你需要使x屬性成為原子,而不是你的整個類,如下所示:

class A
{
    std::atomic<int> x;

    public:
      A() {
        x=0;
      }
      void Add() {
        x++;
      }
      void Sub() {
        x--;
      }     
};

您在原始代碼中獲得的錯誤是完全正常的:除非您為std::atomic<A>提供特化,否則沒有std::atomic<A>::Add方法(請參見此處 )。

引用你的編輯 :你不能通過使用它作為std::atomic模板參數來神奇地使你的class A線程安全。 為了使其線程安全,您可以將其屬性設置為原子(如上所述並提供標准庫為其提供特化),或使用互斥鎖自行鎖定您的資源。 請參閱互斥鎖標頭。 例如:

class   A
{
  std::atomic<int>      x;
  std::vector<int>      v;
  std::mutex            mtx;

  void  Add() {
    x++;
  }
  void  Sub() {
    x--;
  }

  /* Example method to protect a vector */
  void  complexMethod() {
    mtx.lock();

    // Do whatever complex operation you need here
    //  - access element
    //  - erase element
    //  - etc ...

    mtx.unlock();
  }

  /*
  ** Another example using std::lock_guard, as suggested in comments
  ** if you don't need to manually manipulate the mutex
  */
  void  complexMethod2() {
    std::lock_guard<std::mutex> guard(mtx);

    // access, erase, add elements ...
  }

};

將類成員x聲明為原子,然后您不必將對象聲明為原子:

class A
{  
   std::atomic<int> x;
};

. 運算符可以用在一個對象上來調用它的類的成員函數,而不是其他類的成員函數(除非你用這種方式顯式編寫代碼)。

std::atomic<A> a ;
a.Add(); // Here, a does not know what Add() is (a member function of the type parameter)
         // It tries to call Add() method of its own class i.e. std::atomic
         // But std::atomic has no method names Add or Sub

正如@ivanw提到的答案,讓std::atomic<int>成為你的類的成員,然后使用它。

這是另一個例子:

template <typename T> class A
{};

class B { public: void hello() { std::cout << "HELLO!!!"; } };

A<B> a ;
a.hello(); // This statement means that call a's hello member function
           // But the typeof(a) which is A does not have such a function
           // Hence it will be an error.

我認為上面答案的問題在於它們沒有解釋我的想法,至少是問題的模糊性,而且很可能是一個共同的線程發展謬誤。

你不能使一個對象“原子”,因為兩個函數之間的間隔(首先是“讀取x”,然后是“寫入x”)將導致具有其他用途的競賽。 如果您認為需要“原子”對象,那么您需要仔細設計API和成員函數,以便現在公開以開始並提交對象的更新。

如果所有你的意思是“原子”是“對象沒有破壞它的內部狀態”,那么你可以通過std::atomic<>為它們之間沒有不變量的單個普通舊數據類型實現這一點(a doesn不依賴於b)但是你需要對你需要強制執行的任何依賴規則進行某種鎖定。

暫無
暫無

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

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