Потоки могут безопасно считать переменные, установленные событиями VCL?

Для потока действительно ли безопасно СЧИТАТЬ переменную, установленную событием Delphi VCL?

Когда пользователь нажимает на VCL TCheckbox, основной поток устанавливает булевскую переменную на Проверенное состояние флажка.

CheckboxState := CheckBox1.Checked;

В любое время поток читает ту переменную

if CheckBoxState then ...

Не имеет значения, если поток "пропускает" изменение в булевской переменной, потому что поток проверяет переменную в цикл, поскольку это делает другие вещи. Таким образом, это будет видеть изменение состояния в конечном счете...

Действительно ли это безопасно? Или мне нужен специальный код? Действительно ли окружение является чтением, и запись переменной (в потоке и основном потоке соответственно) с критическим кодом называет необходимым и достаточным?

Как я сказал, не имеет значения, если поток получает "неправильное" значение, но я продолжаю думать, что могла бы быть проблема низкого уровня, если один поток пытается считать переменную, в то время как основной поток посреди записи его, или наоборот.

Мой вопрос подобен этому: Перекрестное чтение потока переменной, кто значение, не считают важным.

(Также связанный с моим предыдущим вопросом: Используя EnterCriticalSection в Потоке для обновления маркировки VCL)

5
задан Community 23 May 2017 в 12:01
поделиться

3 ответа

Это безопасно по трем причинам:

  • Только один поток записывает в переменную.

  • Переменная состоит только из одного байта, поэтому невозможно прочитать несогласованное значение. Он будет прочитан либо как Истина , либо как Ложь . Не может быть проблем с выравниванием с булевыми значениями Delphi .

  • Компилятор Delphi не выполняет тщательных проверок, действительно ли переменная записана, и не «оптимизирует» любой код, если это не так. Нелокальные переменные будут считываться всегда, спецификатор volatile не требуется.

При этом, если вы действительно не уверены в этом, вы можете использовать целочисленное значение вместо логического и использовать функцию InterlockedExchange () для записи в переменную. Здесь это перебор, но это хорошая техника, о которой следует знать, потому что для значений размером в одно машинное слово он может устранить необходимость в блокировках.

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

6
ответ дан 13 December 2019 в 22:04
поделиться

В вашем случае (свойство Проверено) операция чтения является атомарной, поэтому она безопасна. То же самое, что и со свойством TThread.Terminated; простые операции чтения и записи для правильно выровненных байтов, слов и двойных слов являются атомарными. Дополнительную информацию можно найти в документации Intel :

ГЛАВА 8 - УПРАВЛЕНИЕ МНОГОПРОЦЕССОРОМ

8.1.1 Гарантированные атомарные операции

Процессор Intel486 (и более новые процессоры с тех пор) гарантирует, что следующее базовые операции с памятью всегда будут выполняться атомарно:

  • Чтение или запись байта
  • Чтение или запись слова, выровненного по 16-битной границе
  • Чтение или запись двойного слова, выровненного по 32-битной границе. -битовая граница

Процессор Pentium (и более новые процессоры с тех пор) гарантирует, что следующие дополнительные операции с памятью всегда будут выполняться атомарно:

  • Чтение или запись четверного слова, выровненного по 64-битной границе
  • 16-битный доступ к некэшированным ячейкам памяти, которые соответствуют 32-битной шине данных
3
ответ дан 13 December 2019 в 22:04
поделиться

Для примера, который вы привели, это будет безопасно. Технически основная проблема возникает в случаях, когда размер вашей переменной превышает машинное слово, и таким образом вы можете получить не синхронизированные старшее слово и длинное слово. Однако для небольших значений это не является проблемой.

Если вы думаете, что это потенциальная проблема, например, при использовании указателя, то лучше использовать TCriticalSection для контроля чтения и записи элемента. Это достаточно быстро для всех практических ситуаций и гарантирует 100% безопасность.

1
ответ дан 13 December 2019 в 22:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: