У нас есть 2 потока, которые асинхронно записывают в переменную tmp числа 322 и 1337. Странность в том, что даже если переменная atomic, условие все-таки иногда срабатывает (причем даже намного чаще, чем если бы переменная было просто int), но в cout все-таки вводится либо 1337 или 322. Объясните пожалуйста как все-таки защитить переменную от считывания во время записи. Казалось бы что на 32битных системах все переменные до 4 байт должны записываться атомарно. Вот код:
#include "pch.h"
#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
int main()
{
setlocale(LC_ALL,"rus");
atomic<int> tmp = 322;
thread th0([&tmp]() {
for (int i = 0; i < 100000000; i++) { tmp = 322; this_thread::sleep_for(chrono::microseconds(2));
}
});
thread th1([&tmp]() {
for (int i = 0; i < 100000000; i++) { tmp = 1337; this_thread::sleep_for(chrono::microseconds(3));
}
});
for (int i = 0; i < 10000000; i++) {
if(tmp!=322&&tmp!=1337)cout << "Ошибка =" <<tmp<< endl;
this_thread::sleep_for(chrono::microseconds(1));
}
th0.detach();
th1.detach();
}
Все тут атомарно (естественно, кроме вычисления всего выражения в if
).
А чего вы ожидали?
Объявив tmp
atomic вы заставили компилятор обращаться к памяти при каждом упоминании tmp
.
Соответственно, в if(tmp!=322&&tmp!=1337)
значение tmp
будет выбираться дважды.
Если первое чтение вернуло 1337, а второе 322, то выполнится
cout << "Ошибка =" <<tmp<< endl;
,
что вы иногда (думаю, довольно редко) и наблюдаете.
Операции tmp!=322
и tmp!=1337
не атомарны, так как std::atomic не имеет функций operator!=, и даже если бы имел то операция && между ними точно не атомарна
Проблема в том, что пока происходит проверка на условие, переменная иногда успевает менять свое значение. Для того чтобы избежать такой проблемы, нужно сохранить во временную переменную значение переменной перед началом проверки
for (int i = 0; i < 10000000; i++) {
int ntmp = tmp;
if(ntmp !=322&& ntmp !=1337)cout << "Ошибка =" <<ntmp<< endl;
this_thread::sleep_for(chrono::milliseconds(1));
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Имеется программа для разбиения строки по регулярному выражению (парсинг)Программа читает строку из файла, разбивает по ";", вписывает в вектор...
Имеется класс, полем которого является структура, а один из методов это работа с этой структуройПри инициализации метода ругается на неправильное...
Хочу сделать что-то типа джойстика на андроидеЕсть квадратный тип и круглый тип
Ранее я использовал Java 8 , где была включена JavaFXХочу настроить работу JavaFX 11 используя Eclipse