![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Возможно ли "зависание" в этом коде из VCL? (критические секции) [D6]
XP © (2005-02-21 17:27:00)Вот текст двух методов из класса TCanvas:
procedure TCanvas.Lock;
begin
EnterCriticalSection(CounterLock);
Inc(FLockCount);
LeaveCriticalSection(CounterLock);
EnterCriticalSection(FLock);
end;
function TCanvas.TryLock: Boolean;
begin
EnterCriticalSection(CounterLock);
try
Result := FLockCount = 0;
if Result then Lock;
finally
LeaveCriticalSection(CounterLock);
end;
end;
Если расписать, то получится следующая картина:
function TCanvas.TryLock: Boolean;
EnterCriticalSection(CounterLock); // (1)
try
Result := FLockCount = 0;
if Result then
begin // вставлено из метода Lock
EnterCriticalSection(CounterLock); // (2)
Inc(FLockCount);
LeaveCriticalSection(CounterLock);
EnterCriticalSection(FLock);
end; // конец вставки
finally
LeaveCriticalSection(CounterLock);
end;
Если мне не изменяет зрение и логика, в строке, помеченной (2), произойдет зависание при попытке входа в критическую секцию, в которую уже зашли в строке (1), то бишь, так называемый BottleNick - сами же себя застопорили.
Но так реализовано у Borland'а.
В чем тут подвох?
Или я неправильно понимаю идеологию критических секций?
Кто подскажет, где правильная формулировка:
1. Критическая секция не позволяет двум потокамвойти одновременно (EnterCriticalSection).
2. Критическая секция не позволяет кому угодно и как угодновойти дважды (EnterCriticalSection).
BiN (2005-02-21 18:03:00) [1]BiN © (21.02.05 17:53) [5]
в [2] приведена не та фраза
читаем как в [1]...
XP (2005-02-21 17:56:00) [2]Так то оно так, но следующий код вызовет возникновение исключительной ситуации, так как Operation2 не сможет получить эксклюзивный доступ к Canvas, ибо FLockCount > 0 (см. код в вопросе):
procedure TMyControl.Operation1;
begin
if Canvas.TryLock then
begin
...
Operation2;
...
end;
end;
procedure TMyControl.Operation2;
begin
if Canvas.TryLock then
...
else
raise Exception.Create('Wait until operation complete.');
end;
И это в контексте одного потока.
Вроде бы ничто не мешает получить доступ к Canvas (в Operation2), но Borland эту возможность блокирует при помощи FLockCount. Вместе с тем, использование Lock вместо TryLock даст, согласно msdn, требуемый результат.
Зачем так реализовано? Должен же быть в этом смысл?
BiN (2005-02-21 17:53:00) [3]пардон
в [2] приведена не та фраза
Вот верный вариант:
"After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns.
"
MBo (2005-02-21 17:41:00) [4]Правильно 1.
В занятую крит. секцию не может войти другой поток
GuAV (2005-02-21 17:40:00) [5]1.
из MSDN
EnterCriticalSection
...
Remarks
...
After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns.
BiN (2005-02-21 17:40:00) [6]Если поток уже владеет критической секцией, ф-я сразу вернет управление
BiN (2005-02-21 17:38:00) [7]"EnterCriticalSection
The EnterCriticalSection function waits for ownership of the specified critical section object. The function returns when the calling thread is granted ownership.
" (c) msdn