Можно было написать "UINT (InCriticalSection) <= UINT (true)", но некрасиво как-то Проверка выполнялась не только внутри критического участка, но и вне его.
Вот Assert периодически и трапался, хотя при этом переменная не выходила за пределы значений true/false.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Все поняли, почему?
Ну вообще-то пример достаточно классический.... Собственно на нем показывают необходимость атомарности операции проверки и установки семафора...
Re: Пример неочевидных граблей :)
От:
Аноним
Дата:
06.04.07 13:12
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали: ЕМ>Можно было написать "UINT (InCriticalSection) <= UINT (true)", но некрасиво как-то Проверка выполнялась не только внутри критического участка, но и вне его.
ЕМ>Вот Assert периодически и трапался, хотя при этом переменная не выходила за пределы значений true/false.
ЕМ>Все поняли, почему?
Здравствуйте, <Аноним>, Вы писали:
А>Я не понял. Можно пояснение ?
При указанном сравнении выполняется две выборки переменной из памяти. Может случиться так, что в момент сравнения с false она имеет значение true, а к моменту сравнения с true успевать измениться на false.
Поэтому нужно либо оборачивать подобные проверки какой-то защитой, либо (что проще и эффективнее) оформлять сравнение так, чтобы выборка была единственной.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>При указанном сравнении выполняется две выборки переменной из памяти. Может случиться так, что в момент сравнения с false она имеет значение true, а к моменту сравнения с true успевать измениться на false.
Вы открыли для себя ситуацию "гонки" (race)
ЕМ>Поэтому нужно либо оборачивать подобные проверки какой-то защитой,
Для этого и существуют средства синхронизации (мютексы etc).
ЕМ>либо (что проще и эффективнее) оформлять сравнение так, чтобы выборка была единственной.
Например?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Вы открыли для себя ситуацию "гонки" (race)
Вы, наверное, думали, что я не знал об этой ситуации? Я привел пример неочевидной гонки.
ЕМ>>либо (что проще и эффективнее) оформлять сравнение так, чтобы выборка была единственной.
ДД>Например?
Например, как уже писалось, "UINT (InCriticalSection) <= UINT (true)".
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Вы, наверное, думали, что я не знал об этой ситуации? Я привел пример неочевидной гонки.
Так если ЕМ>Проверка выполнялась не только внутри критического участка, но и вне его.
то очевидно, что вычисление первой половины выражения в assert'е у первого потока может быть прервано вторым потоком, который войдет в критическую секцию, но не успеет из нее выйти, когда произойдет переключение обратно на первый поток, и он в свою очередь досчитает выражение, и таким образом попадаем в assert.
ЕМ>Например, как уже писалось, "UINT (InCriticalSection) <= UINT (true)".
Брр. Смысл этой проверки — попадает ли значение InCriticalSection в диапазон bool ?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>очевидно, что вычисление первой половины выражения в assert'е у первого потока может быть прервано вторым потоком, который войдет в критическую секцию, но не успеет из нее выйти, когда произойдет переключение обратно на первый поток, и он в свою очередь досчитает выражение, и таким образом попадаем в assert.
После подсказки оно всем очевидно Когда в выражении есть модификация — тоже всем очевидно. А вот в такой форме, и без подсказки — сомневаюсь, что Вы с первого взгляда заметили бы такую возможность
ДД>Смысл этой проверки — попадает ли значение InCriticalSection в диапазон bool ?
Да.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Пример неочевидных граблей :)
От:
Аноним
Дата:
08.04.07 21:16
Оценка:
welcome to the mutithreading world.
Если для Вас эти грабли неочевидны — у Вас еще все впереди
Здравствуйте, <Аноним>, Вы писали:
А>welcome to the mutithreading world.
Спасибо, уже лет примерно тридцать, как
А>Если для Вас эти грабли неочевидны
Я уже говорил — задним умом все сильны Та же самая конструкция, но с проверкой не на равенство, а на "меньше или равно" и "больше или равно" будет работать корректно, независимо от того, защищена она средствами обеспечения исключительности, или нет.
Кстати, оборачивать мьютексами и прочими средствами подобные проверки — вообще дурной тон.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Пример неочевидных граблей :)
От:
Аноним
Дата:
09.04.07 06:35
Оценка:
А>>welcome to the mutithreading world. ЕМ>Спасибо, уже лет примерно тридцать, как
Мсье программил под VMS?
ЕМ>При указанном сравнении выполняется две выборки переменной из памяти. Может случиться так, что в момент сравнения с false она имеет значение true, а к моменту сравнения с true успевать измениться на false.
Здравствуйте, gwg-605, Вы писали:
G6>Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>>При указанном сравнении выполняется две выборки переменной из памяти. Может случиться так, что в момент сравнения с false она имеет значение true, а к моменту сравнения с true успевать измениться на false.
G6>А где там две выборки данных?
Сорри вопрос снят.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Строго говоря, оптимизирующий компилятор это дело свернет в одну выборку, но проверка-то работает как раз в отладочном варианте
Да я этот assert сразу не заметил подумал что-то не так с IntelockedExchange.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ> А вот в такой форме, и без подсказки — сомневаюсь, что Вы с первого взгляда заметили бы такую возможность
Ну не скажите. Мне, например, подозрительно любое место, где идет обращение к разделенным между потоками данным вне критической секции.
ДД>>Смысл этой проверки — попадает ли значение InCriticalSection в диапазон bool ?
ЕМ>Да.
А можно поинтересоваться целью такой проверки?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Мне, например, подозрительно любое место, где идет обращение к разделенным между потоками данным вне критической секции.
Да мне, как бы, тоже, но если я начну еще и дежурные проверки, вызываемые из кучи функций, в критические секции оборачивать — реалтайму вообще труба настанет
ДД>>>Смысл этой проверки — попадает ли значение InCriticalSection в диапазон bool ?
ЕМ>>Да.
ДД>А можно поинтересоваться целью такой проверки?
От нежелательной порчи дикими указателями, кривым кодом компилятора и т.п.
Здравствуйте, ДимДимыч, Вы писали:
ЕМ>>Кстати, оборачивать мьютексами и прочими средствами подобные проверки — вообще дурной тон.
ДД>Это где написано, что дурной тон?
Там же, где описаны и другие приемы сокращения издержек
ДД>Вы уверены, что на любой архитектуре с любым компилятором такая проверка будет атомарной?
Под "подобными" я как раз и подразумевал "самоатомарные", типа (x <= 1). Если на какой-то архитектуре и под каким-то компилятором переменная типа bool выбирается не атомарно — это серьезный повод для отказа от параллелизма в этих условиях.