我有一个想要在不同线程中使用的类,我想我可以这样使用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使类成为线程安全的类?
发布于 2015-06-10 23:58:35
您需要使x属性成为原子属性,而不是整个类,如下所示:
class A
{
std::atomic<int> x;
public:
A() {
x=0;
}
void Add() {
x++;
}
void Sub() {
x--;
}
};您在原始代码中遇到的错误是完全正常的:没有std::atomic<A>::Add方法(请参见here),除非您为std::atomic<A>提供了专门化。
引用您的编辑:您不能通过将其用作std::atomic的模板参数来神奇地确保class A线程的安全。要使其线程安全,您可以将其属性设置为原子属性(如上所述,并且标准库为其提供了专门化),或者使用互斥锁住您的资源。请参阅mutex标头。例如:
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 ...
}
};发布于 2015-06-10 23:51:24
将类成员x声明为原子,这样就不必将对象声明为原子:
class A
{
std::atomic<int> x;
};发布于 2015-06-11 00:02:33
可以在对象上使用.运算符来调用其类的成员函数,而不是其他类的成员函数(除非您以这种方式显式编写代码)。
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.https://stackoverflow.com/questions/30761225
复制相似问题