Вы наверное сталкивались с задачей написания счетчика. Простецкая задачка, не правда ли?
Но так может показаться только на первый взгляд. Ведь при работе с многопоточным программированием код:
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, в которых происходит инкремент счетчика. По окончании выводиться значение счетчика.