Объясните суть атомарных операций

280
01 июня 2017, 09:57

Вопрос по поводу атомарных операций...
Берем, допустим, инкремент, выполняется следующее:

1)грузим в регистр значение переменной
2)инкрементируем
3)выгружаем из регистра в память

Если начинаем делать это из разных потоков, то можем старое значение считывать, это понятно...

Однако, с помощью какой магии атомарные типы из разных потоков позволяют такое проворачивать без ошибок? что значит атомарный тип? это свойство определенного типа или это можно гарантировать для любого типа?
Ну и код:

#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
int main()
{
using namespace std::chrono_literals;
//std::atomic<long long> i{1};
//std::atomic<long long> ii{2};
long long i = 1;
long long ii = 2;
std::thread t1([&](){ i++; i--; ii++; });
std::thread t2([&](){ i++; i--; ii++; });
std::thread t3([&](){ i++; i--; ii++; });
std::thread t4([&](){ i++; i--; ii++; });
t1.join();
t2.join();
t3.join();
t4.join();
std::this_thread::sleep_for(100ms);
std::cout<<i<<" "<<ii;
}

почему что для атомарных типов, что для неатомарных выводится всегда 1 6... не должно же быть такого

Answer 1

Вы не дали ни единого шанса :) - такой короткий поток успеет все сделать и завершиться без переключения.

Например,

    long long i = 1;
    long long ii = 2;
    std::thread t1([&](){ for(int q = 0; q < 1000000; ++q){ i++; i--; ii++;}});
    std::thread t2([&](){ for(int q = 0; q < 1000000; ++q){ i++; i--; ii++;}});
    std::thread t3([&](){ for(int q = 0; q < 1000000; ++q){ i++; i--; ii++;}});
    std::thread t4([&](){ for(int q = 0; q < 1000000; ++q){ i++; i--; ii++;}});
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    //std::this_thread::sleep_for(100ms); - это нафиг не нужно!!!
    std::cout<<i<<" "<<ii << std::endl;
}

дает при компиляции VC++2015 и выполнении на четырехъядерном процессоре что-то типа

4794 1815494

Меняем на атомарные - и получаем (с заметной задержкой)

1 4000002

Все ясно?

READ ALSO
Задача С++ на цикл! [требует правки]

Задача С++ на цикл! [требует правки]

Найти значение функции, используя ее расписание в ряд Тейлора ln x

185
Как прописать путь к элементу через xpath для использования в JavascriptExecutor

Как прописать путь к элементу через xpath для использования в JavascriptExecutor

Канва: пишу автотест на selenium WebDriverЕсть Вебэлемент с локатором CSS

416
JS - Как посчитать значение арифметического выражения из строки

JS - Как посчитать значение арифметического выражения из строки

Пытаюсь сделать калькуляторРаботает он следующим образом: При клике по цифре, она вписывается в переменную

429