Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Delphi: WinAPI и системное программирование > "Атомарность" чтения/записи переменной |
Автор: BofA 29.12.2008, 15:06 |
Добрый день. Возник глупый вопрос слеующего типа. Допустим, есть два потока, один из них записывает данные в глобальную переменную, а другой читает их. Никаких методов синхронизации не используется. Правильно ли я понимаю, что читающий поток будет получать последнее записанное до чтения значение (т.е. не может случиться такого, что потоки одновременно обратятся к переменной и из-за конфликта читающий поток получит мусор)? Подразумевается, что переменная - обычный Integer (правильно ли я понимаю, что в случае, к примеру, с record, читающий поток может получить запись, содержащую половину предыдущей и половину обновлённой записи в случае конфликта?) |
Автор: bems 29.12.2008, 20:03 |
даже с простым integer небезопасно. Юзай Interlocked-функции |
Автор: ReInit 8.1.2009, 19:45 | ||
bems, глупости, чтение и запись дворда потокопезопасна даже в мультипроцессорной среде... Добавлено через 2 минуты и 59 секунд
Нет, читающий поток получит всегда определенное значение переменной. Недозаписанных двордов быть не может. |
Автор: Alexeis 8.1.2009, 19:58 |
Я себе думаю так, все семафоры и прочие глобальные объекты синхронизации ни что иное как обычные объекты в системной области. Если один поток меняет состояние глобального объекта, то другой в это время может его читать. И все происходит правильно. Получается если тип совпадает с разрядностью регистра и операция занимает один такт, то все будет верно, однако используя высокоуровневый язык нельзя гарантировать что операция займет один такт. Вообще, часто встречаются ситуации когда некоторые данные неявно связанны между собой, потому безобидная на первый взгляд операция может привести к непредсказуемым результатам, поскольку 2 потока меняют связанные между собой параметры одновременно. В связи с этим лучше избежать несинхронизированного доступа. Если нужен многопоточный счетчик используйте семафор. |
Автор: ReInit 9.1.2009, 01:03 | ||||
CodeMonkey, Да, конечно я имел ввиду выровненные данные. Delphi впрочем, по умолчанию их выравнивает.
Количество тактов тут не причем. Даже на ЯВУ дворд не будет считываться/записываться побайтно или пословно, он будет считываться/записываться именно двордом, и это будет происходит атомарно (опять оговорюсь - для выровненных данных).
??? |
Автор: Riply 9.1.2009, 01:22 | ||
Не надо быть столь категоричным ![]() Есть люди, не согласные с Вами в этом вопросе. Например, Рихтер ![]() |
Автор: Alexeis 9.1.2009, 01:36 | ||
Я имел ввиду тот случай когда 2 потока читают и пишут в одну переменную. Классический пример, когда идут 3 асмовские команды и в зависимости от того на какой команде прервали получается разный результат. Если всего одна команда inc, а не 3 то все будет верно. Я сейчас не вспомню пример, но где-то у Петровича было. Одна переменная вычисляется через другую двумя потоками, вроде как оба потока делают безопасные операции, но результат неверный. Нужно курить маны ![]() |
Автор: CodeMonkey 9.1.2009, 03:21 |
Помимо всего прочего, Interlocked-функции включают в себя http://en.wikipedia.org/wiki/Memory_barrier, чего точно нет у обычного чтения. По ссылке же пример. Хотя там значения получаются "целиком", но не те, какие мы ожидаем. Ещё пример можно увидеть http://msdn.microsoft.com/ru-ru/magazine/cc817398.aspx (пункт "Свободное от блокировок переупорядочение"). |
Автор: RinOSpro 2.2.2009, 16:08 | ||
Процитирую один документик посвященный многопоточности ![]()
Казалось бы что может быть проще? К несчастью, даже этот простой код может вызвать проблемы, если два потока используют его для увеличения общей переменной A. Этот единственный оператор Паскаля транслируется в три действия на ассемблерном уровне. Чтение A из ячейки памяти в регистр процессора. Увеличение регистра процессора на 1. Запись содержимого регистра процессора в ячейку памяти A. http://ipicture.ru/ Однако нет никакой гарантии, что все именно так и произойдет. Закон Мерфи гласит, что может случиться следующее: http://ipicture.ru/ В этом случае А увеличивается не на два, а только на единицу. Конечно, если А является положением индикатора, то это, скорее всего, не проблема, но если А - что-нибудь более важное, подобно счетчику количества элементов в списке, тогда жди беды. Если общая переменная является указателем, то можно наткнуться на самые разные неприятные результаты. Это иногда называют race condition (конфликт, конкуренция потоков). Подробнее читайте в первой ссылке или см вложение, там в формате doc. |