Предполагая, что x является общей переменной потока, а func всегда возвращает 0, содержит ли приведенный ниже код гонку данных в терминах C11 и C ++ 11? Пожалуйста, предположим, что x написан в двух разных потоках, всегда с надлежащей блокировкой, кроме оператора switch ниже.
int x; // global variable
...
int y; // local variable
...
switch (func())
{
case 1:
{
x = 0;
y = 1;
break;
}
case 2:
{
x = 0;
y = 2;
break;
}
case 3:
default:
{
y = 3;
break;
}
}
В стандарте есть примечание (как C11, так и C ++ 11), которое исключает преобразования компилятора, которые вводят в код гонку данных. Разрешено ли компилятору преобразовывать код, как показано ниже? Приведенный ниже код, безусловно, содержит гонку данных, но вопрос в том, внедрил ли его компилятор или он уже был в исходном коде. Был незащищенный доступ к общей переменной, хотя и недоступный.
int x; // global variable
...
int y; // local variable
...
temp = x;
x = 0;
switch (func())
{
case 1:
{
y = 1;
break;
}
case 2:
{
y = 2;
break;
}
case 3:
default:
{
x = temp;
y = 3;
break;
}
}
В стандарте C ++ определяется гонка:
1.10 / 4: Две оценки выражений конфликтуют, если одна из них изменяет ячейку памяти, а другая обращается к или
изменяет ту же ячейку памяти1.10 / 21: Выполнение программы содержит гонку данных, если она содержит два конфликтующих действия в разных потоках, по крайней мере, один из
который не является атомным, и ни один не происходит раньше другого. Любое такое
гонка данных приводит к неопределенному поведению.
Предположим, что у вас есть несколько потоков, выполняющих один и тот же код, из-за того, что func()
будет всегда возвращать 0 (ваше утверждение), ни один из потоков не может изменить содержание х. Кроме того, y — локальная переменная функции, выполняемой потоком, поэтому она не является общей. Следовательно, в этом сценарии не может возникнуть состояние гонки.
Компилятору не разрешено выполнять преобразования, соответствующие второму фрагменту, потому что:
1,10 / 22: Преобразования компилятора, которые вводят назначения в потенциально разделяемую область памяти, которая не будет изменена
абстрактные машины обычно исключаются этим стандартом, поскольку такие
назначение может перезаписать другое назначение другим потоком
в случаях, когда выполнение абстрактной машины не будет иметь
столкнулся с гонкой данных.
Но если вы сами напишите фрагмент, в условиях, описанных выше, могут возникнуть условия гонки, поскольку x не является атомарным, и доступ к чтению может быть в одном потоке (temp=x
) и доступ для записи в другом (либо x=0
или в разделе по умолчанию другого потока (x=temp
)
Других решений пока нет …