Возможные цифры результата «я» - PullRequest
1 голос
/ 17 февраля 2012
int i=5;
f()
{
    i++;
    i--;
}

Для приведенного выше кода, если три потока одновременно выполняют вышеуказанную функцию f(), тогда какие могут быть общие значения глобальной переменной i?

Примечание: i инициализируется до 5 глобальных значений.

Ответы [ 5 ]

10 голосов
/ 17 февраля 2012

Я бы сказал, что это упражнение в комбинаторике, которое я лично не собираюсь выполнять, однако хочу пояснить, что это НЕ правильный способ заставить потоки выполнять это f(),Проблема состоит в том, что реализация operator++ не является отдельной инструкцией, что означает, что в середине одного вызова к operator++ она может переключать контекст и делать еще один f() в другом потоке.Это может привести к повреждению вашей переменной i.

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

6 голосов
/ 17 февраля 2012

Предположим, что оператор ++ определен в виде инструкций:

1) Load the memory location holding i into register A. 
2) Add one to the value stored at register A. 
3) Store register A back into memory holding i."

Теперь у нас есть 3 потока, и поскольку инструменты синхронизации отсутствуют, нет гарантии, когдаОС переключит контекст между этими потоками.

Итак, вот возможный сценарий.

1) Поток 1 загружает i в регистр A. Регистр A содержит значение 5.

2) Поток 1 добавляет единицу к регистру A. Теперь регистр A содержит значение 6.

3) Контекст ОС переключается на Поток 2.

4) Поток 2 загружает i изпамять в регистр A перезаписывает туда предыдущее значение .Регистр A теперь содержит значение 5.

5) Поток 2 добавляет единицу в регистр A. Регистр A теперь снова содержит значение 6.

6) Сохранение потока 2зарегистрировать A обратно в память для переменной i.я храню значение 6.

7) контекст ОС переключается обратно на поток 1.

8) поток 1 продолжается с того места, где он остановился, сохраняет регистр A обратно в память для переменной i.i still содержит значение 6.

Здесь мы «успешно» прошли через два полных оператора приращения и привели к добавлению только одного значения в переменную.О, опасность многопоточности ...

2 голосов
/ 17 февраля 2012

Программа имеет бесконечно много возможных результатов (хотя существует только конечное число возможных значений переменной int), так как она вызвала неопределенное поведение, обращаясь к одному и тому же объекту из нескольких потоков без синхронизации.

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

0 голосов
/ 17 февраля 2012

i может перейти от 00000000 00000000 00000000 00000000 до 11111111 11111111 11111111 11111111 в двоичном формате, при условии, что это int32.

Вот, пожалуйста.

0 голосов
/ 17 февраля 2012

Это домашнее задание?Я думаю, что любое целочисленное значение от 3 до 7. Ответ:

  • 8 не может произойти, потому что последний поток будет уменьшать значение без какого-либо вмешательства со стороны других потоков.
  • 2 не можетбыть достигнутым, потому что по крайней мере первое увеличение будет успешным.
  • Мы предполагаем, что чтение / запись памяти является атомарным.В противном случае могут произойти странные операции на битовом уровне.

Однако, если вы включите оптимизацию, я ожидаю, что на самом деле ни один из потоков меня не изменит.

...