Вы наверное сталкивались с задачей написания счетчика. Простецкая задачка, не правда ли?
Но так может показаться только на первый взгляд. Ведь при работе с многопоточным программированием код:
struct Counter {
int value;
void increment(){
++value;
}
void decrement(){
--value;
}
int get() {
return value;
}
};
Перестает работать так как ожидается. В один и тот же момент к методам счетчика может происходить обращение из разных потоков программы, в результате чего вы можете потерять данные или вовсе испортить результат.
Для избежания подобной ситуации можно воспользоваться уже наверняка знакомые читателю мьютексы. Но в этой статье речь пойдет о куда более простом инструменте из новой спецификации С++ 2011.
Теперь в С++11 предусмотрены так называемые Atomic Types. Переменная объявленная как атомарная будет лишена недостатков, которые не давали коду выше работать нормально.
Чтобы объявить нужно использовать инклуд:
#include <atomic>
После чего просто объявить переменную таким образом:
std::atomic<type> value;
Пример реализации:
#include <atomic>
#include <thread>
#include <iostream>
struct AtomicCounter {
std::atomic<int> value;
void increment(){
++value;
}
void decrement(){
--value;
}
int get(){
return value.load();
}
};
AtomicCounter counter;
void hello() {
for (int i=0;i<100;i++) {
counter.increment();
}
}
int main(){
// создаем потоки
std::thread t1(hello);
std::thread t2(hello);
std::thread t3(hello);
t1.join();
t2.join();
t3.join();
std::cout << counter.get() << std::endl;
return 0;
}
В программе использованы потоки С++11, в которых происходит инкремент счетчика. По окончании выводиться значение счетчика.
