Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Так присвоение булевой переменной атомарное или нет?


Kolan ©   (2008-06-02 16:59:00) 

Помню было обсуждение, а чем кончилось забыл.

Вопрос простой:
Может ли статься так, что в коде:

if Flag then {1}
 DoSmth;    {2}

в {1} Flag будет False, а в {2} уже True? На много ядерной(процессорной) машине.


oxffff   (2008-06-03 21:45:00) [1]


> Kolan ©   (02.06.08 18:21) [7]
> > Нет, не может.
>
> Ладно, а так:
> if Flag then {<--— Поток 1 проверяет Flag и он False}
>  Break;
>                   {<--— Поток 2 устанавливает Flag в True}
> DoSmth;     {<--— Получается что поток 1 проверил флаг,
> но эта проверка уже не правильная.}


Это не очень удачный пример.
Поскольку здесь явно отсутствует необходимая синхронизация.

Более удачный пример сбоя на многопроцессорной машине можешь найти в MSDN Synchronization and Multiprocessor Issues

int iValue;
BOOL fValueHasBeenComputed = FALSE;
extern int ComputeValue();

void CacheComputedValue()
{
 if (!fValueHasBeenComputed)
 {
   iValue = ComputeValue();
   fValueHasBeenComputed = TRUE;
 }
}

BOOL FetchComputedValue(int *piResult)
{
 if (fValueHasBeenComputed)
 {
   *piResult = iValue;
   return TRUE;
 }
 else
   return FALSE;
}


There is a race condition in this code on multiprocessor systems because the processor that executes CacheComputedValue the first time may write fValueHasBeenComputed to main memory before writing iValue to main memory. Consequently, a second processor executing FetchComputedValue at the same time reads fValueHasBeenComputed as TRUE, but the new value of iValue is still in the first processor's cache and has not been written to memory.


Leonid Troyanovsky   (2008-06-03 18:10:00) [2]


> Kolan ©   (02.06.08 18:21) [7]

http://msdn.microsoft.com/en-us/magazine/cc302329.aspx

--
Regards, LVT.


Рамиль   (2008-06-03 10:02:00) [3]


> то он в любом случае должен быть выполнен непрерывно вместе
> с условием.

В смысле надо обеспечить непрерывное выполнение.


Рамиль   (2008-06-03 10:01:00) [4]

А какая разница, будет он уже true или false? Если при изменениии флага рушится что нибудь, к чему получает доступ код после условия, то он в любом случае должен быть выполнен непрерывно вместе с условием.
А иначе разница в десятках миллесекунд значения не имеет (в Windows)


Тимохов   (2008-06-03 01:58:00) [5]

могу сказать, что в общем плане очень развивает код из TMultiReadExclusiveWriteSynchronizer

они там имитируют TLS (thread local storage).

посмотри, многое моймешь... и не имхо.

вернее почти ничего, скорее всего, не поймешь, но поймешь, что ты лошок в НАСТОЯЩЕМ многопоточном программировании, как и многие другие (я в том числе).


Игорь Шевченко   (2008-06-02 22:46:00) [6]

не надо присвоение с проверкой путать - это две операции :)


DVM   (2008-06-02 22:35:00) [7]


> Присвоение, что Boolean, что BOOL - атомарное.

Я думаю, это зависит в общем случае от компилятора. В Delphi атомарное, а вот скажем, в SuperPuperFreePascal не обязательно.


tesseract   (2008-06-02 20:36:00) [8]


>  Break;                   {<--— Поток 2 устанавливает Flag
> в True}DoSmth;     {<--— Получается что поток 1 проверил
> флаг, но эта проверка уже не правильная.}


DoSmth выполняться начнёт по правильному, но вот закончит ли ? А так логика неправильная. Потоки легче воспринимать, как независимые объекты изредка получающие / принимающие данные в основной поток.  И смысл из применять только понимая что ограничить поток данных в поток и из него - ключевой момент, особенно на многопроцессорных системах, где из-за этого можно получить нихилую потерю производительности ( AMD с её nUMA не всчёт).


Kolan   (2008-06-02 18:21:00) [9]

> Нет, не может.

Ладно, а так:
if Flag then {<--— Поток 1 проверяет Flag и он False}
 Break;
                  {<--— Поток 2 устанавливает Flag в True}
DoSmth;
    {<--— Получается что поток 1 проверил флаг, но эта проверка уже не правильная.}


Leonid Troyanovsky   (2008-06-02 18:19:00) [10]


> Kolan ©   (02.06.08 16:59)  

Присвоение, что Boolean, что BOOL - атомарное.

--
Regards, LVT.


DiamondShark   (2008-06-02 18:14:00) [11]


> Может ли статься так, что в коде:
>
> if Flag then {1}
>  DoSmth;    {2}
>
> в {1} Flag будет False, а в {2} уже True?

Нет, не может.
Если в {1} Flag будет False, то {2} уже не выполнится.

Может быть, что в {1} Flag будет True, а к моменту выполнения {2} он уже будет False.


> И как бороться? Делать синхронизацию?

Зависит от того, что происходит в DoSmth.
В общем случае -- делать.


Kolan   (2008-06-02 18:09:00) [12]

Ясно, что-то я думал, что в случае с проверкой об этом думать не надо.


tesseract   (2008-06-02 17:59:00) [13]


> И как бороться? Делать синхронизацию?


Естественно. Доступ к данным из потоков всегда надо семафорить. Или сообщения главному потоку постить, чтобы он там семафорил.


Kolan   (2008-06-02 17:21:00) [14]

> И даж на одноядерной. А причем тут атомарность?

То есть может быть такая ситуация:
if Flag then {


ага0   (2008-06-02 17:05:00) [15]

Канэчна может. И даж на одноядерной. А причем тут атомарность?


Наверх

Титульная страница Поиск, карта сайта Написать письмо