#c #objective-c #c 11 #stl #synchronization
#c #objective-c #c 11 #stl #синхронизация
Вопрос:
Я определил атомарную переменную current внутри некоторого файла Obj-C.:
std::atomic<long long> current;
после этого оно было инициировано:
current=4;
После этого переменная стала доступной по количеству потоков.
Некоторые потоки модифицировали переменную следующим образом:
current=(current.fetch_add(1))%4;
В то время как другие потоки изменяли переменную по-другому:
current.fetch_add(1);
if(current>=4){
current=0;
}
Наконец, выполняется следующая строка:
long long cs=current;
На этом этапе произошло нечто странное: в отладчике появляется, что cs равно 4, в то время как current имеет другое значение, обычно 1.
Я ожидал, что cs должен иметь последнее значение current и никогда не должен превышать 3 .
Я проверил все другие экземпляры current ; их не так много, и они используются везде должным образом.
Чего мне не хватает?
Комментарии:
1. Неправильные ожидания атомарного поведения. Скачки между чтением и записью.
2. только опечатка, ничего больше.
3. Может быть много путей выполнения, которые приведут к наблюдаемым результатам. Показанные шаблоны доступа фундаментально нарушены для их заявленной цели.
4. Примечание:
current=4;
это присваивание, а не инициализация.
Ответ №1:
Атомарные значения не являются примитивами синхронизации. Один из возможных потоков выполнения:
current.fetch_add(1); // T1
long long cs=current; // T2
if(current>=4){ // T1
current=0;
}
И
auto tmp = current.fetch_add(1); // T1
long long cs=current; // T2
current=tmp%4; // T1
Решение заключается в использовании мьютексов или спин-блокировок с обменом сравнениями.
Ответ №2:
Это сценарий, который с большой вероятностью может произойти в многопоточной среде. Предположим, что только 2 потока, основной поток, который я назвал здесь THREAD-2, и рабочий поток THREAD-1. Давайте начнем с current, имеющего значение 3, и теперь оно увеличивается ПОТОКОМ-1, в то время как ПОТОК-2 обновляет переменную cs.
THREAD-1: current.fetch_add(1);
THREAD-2: cs = current;
THREAD-1: if(current>=4){ current=0; }
как вы можете видеть, cs получает это значение, когда current равно 4.
Кроме того, это не проблема objective-c, это только C .