Всегда ли незащищенный доступ к разделяемой переменной является гонкой данных?

Предполагая, что 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;
}
}

5

Решение

В стандарте C ++ определяется гонка:

1.10 / 4: Две оценки выражений конфликтуют, если одна из них изменяет ячейку памяти, а другая обращается к или
изменяет ту же ячейку памяти

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

Предположим, что у вас есть несколько потоков, выполняющих один и тот же код, из-за того, что func() будет всегда возвращать 0 (ваше утверждение), ни один из потоков не может изменить содержание х. Кроме того, y — локальная переменная функции, выполняемой потоком, поэтому она не является общей. Следовательно, в этом сценарии не может возникнуть состояние гонки.

Компилятору не разрешено выполнять преобразования, соответствующие второму фрагменту, потому что:

1,10 / 22: Преобразования компилятора, которые вводят назначения в потенциально разделяемую область памяти, которая не будет изменена
абстрактные машины обычно исключаются этим стандартом, поскольку такие
назначение может перезаписать другое назначение другим потоком
в случаях, когда выполнение абстрактной машины не будет иметь
столкнулся с гонкой данных.

Но если вы сами напишите фрагмент, в условиях, описанных выше, могут возникнуть условия гонки, поскольку x не является атомарным, и доступ к чтению может быть в одном потоке (temp=x) и доступ для записи в другом (либо x=0 или в разделе по умолчанию другого потока (x=temp)

4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector