繁体   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