I have a class that I want to use in different threads and I think I may be able to use std::atomic
this way:
class A { int x; public: A() { x=0; } void Add() { x++; } void Sub() { x--; } };
and in my code:
std::atomic<A> a;
and in a different thread:
a.Add();
and
a.Sub();
but I am getting an error that a.Add()
is not known. How can I solve this?
Is there any better way to do this?
Please note that it is an example, and what I want is to make sure that access to class A is thread-safe, so I can not use
std::atomic<int> x;
How can I make a class thread-safe using std::atomic
?
std::atomic is specialized for all integral types to provide member functions specific to integral (like operators ++, --, fetch_add, fetch_sub, ...).
In order to solve this problem, C++ offers atomic variables that are thread-safe. The atomic type is implemented using mutex locks. If one thread acquires the mutex lock, then no other thread can acquire it until it is released by that particular thread.
(C++11) [edit] The atomic library provides components for fine-grained atomic operations allowing for lockless concurrent programming. Each atomic operation is indivisible with regards to any other atomic operation that involves the same object. Atomic objects are free of data races.
You need to make the x
attribute atomic, and not your whole class, as followed:
class A { std::atomic<int> x; public: A() { x=0; } void Add() { x++; } void Sub() { x--; } };
The error you get in you original code is completely normal: there is no std::atomic<A>::Add
method (see here) unless you provide a specialization for std::atomic<A>
.
Referring your edit: you cannot magically make your class A
thread safe by using it as template argument of std::atomic
. To make it thread safe, you can make its attributes atomic (as suggested above and provided the standard library gives a specialization for it), or use mutexes to lock your ressources yourself. See the mutex header. For example:
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 ... } };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With