Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.221.239.148] |
|
Сообщ.
#1
,
|
|
|
В С++ есть модификатор volatile, а в дельфи аналог этого модификатора есть? В проекте одна переменная записывается в потоке, а другие потоки эту переменную читают. Чтобы не было одновременного доступа к переменной существуют ли в дельфи какие то средства синхронизации, или нет. Или надо пользоваться мьютексами?
|
Сообщ.
#2
,
|
|
|
volatile не защищает от одновременного доступа к переменной, он лишь гарантирует, что в каждый момент существует только одна копия переменной. Если переменная простая, чтение её атомарное, то этого может быть достаточно для обеспечения корректного поведения.
В Delphi для Windows volatile нет (для других платформ предусмотрено, не знаю, реализовано ли). Компилятор Delphi не оптимизирует обращения к переменным из разных процедур, размещая их в регистрах, так что простая схема - один раз прочитал переменную в копию, и используй, аналогично с записью, тоже дает защиту от неожиданных изменений при определенных сценариях. При необходимости можно читать с помощью IntelockedExchange. В более сложных случаях - критические секции. |
Сообщ.
#3
,
|
|
|
Я не понял про регистры. Дельфи может размещать переменные в регистрах и при выходе из функции (а переменная описана вне функции) значение теряется?
|
Сообщ.
#4
,
|
|
|
Надо обработать переменную - прочитали ее в регистр, поработали, выгрузили назад. Серьезный оптимизирующий компилятор мог бы держать ее в регистре, пока она кому-то еще нужна, но дельфийский не таков.
|
Сообщ.
#5
,
|
|
|
На х32 регистров так мало, что в реальных применениях это едва ли даст хоть какой-то выхлоп.
|
Сообщ.
#6
,
|
|
|
Цитата a_n_y_a @ Или надо пользоваться мьютексами? Надо пользоваться мьютексами, критическими секциями и не разглагольствовать про регистры - в данном случае это ни к чему. |
Сообщ.
#7
,
|
|
|
Цитата a_n_y_a @ Я не понял про регистры. Дельфи может размещать переменные в регистрах и при выходе из функции (а переменная описана вне функции) значение теряется? Нет, значения переменных не теряются. В регистры помещаются копии переменных. В Сях это соглашение о вызовах называется "fastcall". А в Delphi - "register". Но смысл один и тот же. Что касается синхронизации - тут тебе уже MBo ответил - либо семейство Interlocked - функций, либо критические секции. |
Сообщ.
#8
,
|
|
|
Цитата a_n_y_a @ Причём тут вообще оптимизация и причём тут регистры? Delphi тоже держит локальные переменные в регистрах, но здесь они не локальные. Тем более, если это переменная, которая используется в нескольких потоках, то ни в каких регистрах она хранится не может даже в Си (у каждого потока свои значения регистров, которые с другими потоками никак не пересекаются).Надо обработать переменную - прочитали ее в регистр, поработали, выгрузили назад. Серьезный оптимизирующий компилятор мог бы держать ее в регистре, пока она кому-то еще нужна, но дельфийский не таков. В общем, работа через регистры не защитит переменную от влияния других потоков. Другое дело, что эти Interlocked можно написать на ассемблере с префиксом lock (кроме xchg - она lock'а не требует, использует автоматически). Но если не знаешь как, то тогда Interlocked. Добавлю, что Interlocked-функции есть смысл использовать только при единственном изменении (скажем, прочитать старое значение, одновременно записать новое или увеличить/уменьшить значение). В остальных случаях критические секции. Ну ещё можно использовать запись и чтение из переменной - в это время другие потоки в неё ничего не запишут. Но только как разовую операцию (т.е. прочитать, изменить и записать обратно не прокатит - в этот процесс можно вклиниться). Нужно только убедиться, что переменная имеет размерность не более 32 бит или 64-х для 64-битного режима (иначе Delphi будет проводить данную операцию поэтапно, т.е. их будет 2 или более) и включено выравнивание {$A8}. p.s. Если же задача в том, чтобы использовать одно ИМЯ переменной, но чтобы сами переменные были разные, то тут либо объявить её в классе потока, либо threadvar вместо var |