Успешность записи с одновременным чтением

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

bool myGlobalVariable = false;
void thread1() {
    myGlobalVariable = true;
}
void thread2() {
    bool x = myGlobalVariable; //x is undefined
}

В этом случае после завершения обоих потоков myGlobalVariable гарантированно будет true?

Мне особенно интересно узнать о gcc в linux, но мне было бы интересно узнать, что делают другие операционные системы и компиляторы, или если ARM ведет себя не так, как x86.

2 ответа

Решение

Я не могу понять, как это может не записать значение при любых обстоятельствах, если это просто запись, а не чтение.

Причина, по которой многопоточный доступ к одной и той же переменной опасен, заключается именно в том, что не выполняется проверка того, была ли переменная изменена во время операции. Дело не в том, что он может проверить, а потом жаловаться.

Так что в случае одной записи, и просто записи (так что нет i++, который также читается), он должен быть успешным.

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

Как указывает Антон в своем ответе, спецификация говорит, что это неопределенное поведение, и поэтому можно было бы написать действительный компилятор C++, который преднамеренно следит за таким поведением и рандомизирует результат. Но никакой компилятор не собирается делать это на практике.

Тем не менее, никогда не стоит полагаться на поведение, которое официально не определено, поэтому, как говорится в комментарии от jeffamaphone, правильный ответ на ваш вопрос заключается в том, что запись будет успешной, но вы все равно не должны этого делать.

На практике ничего, вероятно, не получится. Тем не менее, стандарт C++11/14 довольно ясен в этом отношении. Вот цитата из черновика раздела C++14 [intro.multithread]/23 (выделение мое):

Выполнение программы содержит гонку данных, если она содержит два потенциально одновременных конфликтующих действия, по крайней мере одно из которых не является атомарным, и ни одно не происходит раньше другого, за исключением специального случая для обработчиков сигналов, описанных ниже. Любая такая гонка данных приводит к неопределенному поведению.

Где конфликтующие действия определены в [intro.multithread]/6:

Две оценки выражений конфликтуют, если одна из них изменяет ячейку памяти (1.7), а другая обращается или изменяет ту же ячейку памяти.

Другие вопросы по тегам