Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Ошибка считывания/записи переменной в 3х потоках с использованием atomic и без (с++)

#cpp #многопоточность #atomic


У нас есть 2 потока, которые асинхронно записывают в переменную tmp числа 322 и 1337.
Странность в том, что даже если переменная atomic, условие все-таки иногда срабатывает
(причем даже намного чаще, чем если бы переменная было просто int), но в cout все-таки
вводится либо 1337 или 322. Объясните пожалуйста как все-таки защитить переменную от
считывания во время записи. Казалось бы что на 32битных системах все переменные до
4 байт должны записываться атомарно.
Вот код:

#include "pch.h"
#include 
#include 
#include 
using namespace std;

int main()
{
    setlocale(LC_ALL,"rus");
    atomic 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 << "Ошибка =" <


Ответы

Ответ 1



Все тут атомарно (естественно, кроме вычисления всего выражения в if). А чего вы ожидали? Объявив tmp atomic вы заставили компилятор обращаться к памяти при каждом упоминании tmp. Соответственно, в if(tmp!=322&&tmp!=1337) значение tmp будет выбираться дважды. Если первое чтение вернуло 1337, а второе 322, то выполнится cout << "Ошибка =" <

Ответ 2



Операции tmp!=322 и tmp!=1337 не атомарны, так как std::atomic не имеет функций operator!=, и даже если бы имел то операция && между ними точно не атомарна

Ответ 3



Проблема в том, что пока происходит проверка на условие, переменная иногда успевает менять свое значение. Для того чтобы избежать такой проблемы, нужно сохранить во временную переменную значение переменной перед началом проверки for (int i = 0; i < 10000000; i++) { int ntmp = tmp; if(ntmp !=322&& ntmp !=1337)cout << "Ошибка =" <

Комментариев нет:

Отправить комментарий