![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
wait functions
Polevi © (2006-02-01 12:09:00)несколько потоков ждут семафор
насколько возможно предсказать в каком порядке потоки проснуться при вызове ReleaseSemaphore ?
FIFO, LIFO или случайным образом ?
у меня есть пул потоков который обслуживает запросы клиентов
пул наращиваемый, алгоритм удаления потока следующий - он удаляется если ждет объекта более 1 минуты к примеру
я опасаюсь что данный алгоритм не будет работать если потоки будут получать управление в порядке вызова ими Wait ф-ии, в моем случае они будут получать управление по очереди даже если будет только один клиент
какие будут соображения, господа ?
Digitman (2006-02-01 16:15:00) [21]
> Polevi © (01.02.06 15:59) [26]
> RS вызывает транспортный поток
Тогда поясни, какое дело логике транспортного потока до логики потока-диспетчера пула ?
Игорь Шевченко (2006-02-01 16:15:00) [22]
> но поскольку работает механизм FIFO на каждый васин запрос
> будет просыпаться следующий поток, и таймаута ни один из
> них не дождется
Я вот этого момента честно не понимаю, почему ни один не дождется таймаута ?
Polevi (2006-02-01 16:02:00) [23]этот код я привел чтобы показать что после добавления нового потока он обрабатывает запрос и не уничтожается
Polevi (2006-02-01 16:01:00) [24]>Rouse_ © (01.02.06 15:53) [24]
ну и чем твоя логика отличается от моей интересно
procedure TWorkThread.Execute;
var
arr:array[0..1] of THandle;
ir:TInvokeRequest;
res:TMemoryStream;
client:TClient;
begin
arr[0]:=FWaitDataSem;
arr[1]:=FStopEvent;
CoInitialize(nil);
while not Terminated do
begin
case WaitForMultipleObjects(2,@arr[0],false,WORKTHREAD_TIMEOUT) of
WAIT_OBJECT_0: //request
begin
ir:=FReqResQueue.GetRequest(client);
try
try
res:=ir.Invoke;
except on E:Exception do
res:=CreateExceptionResponse(E.Message);
end;
FReqResQueue.AddResponse(client,res);
finally
ir.Free;
end
end;
WAIT_TIMEOUT:
begin
if FThreadPool.Remove(self) then Terminate;
end;
WAIT_OBJECT_0+1: //stop
begin
Terminate;
end
end;
end;
CoUninitialize;
end;
Polevi (2006-02-01 15:59:00) [25]>Digitman © (01.02.06 15:46) [23]
ты не в теме, RS вызывает транспортный поток
Polevi (2006-02-01 15:57:00) [26]попытаюсь обяснить еще раз что мне надо
у меня наращиваемый пул
необходимо определить условия при которых в него добалвяются и удаляются потоки
алгоритм добавления таков - специальный watch поток следит за очередью клиентских запросов и если находит запрос который лежит там больше X - он добавляет поток в пул
алгоритм удаления был мной сформулирован след. образом - рабочий поток пытается дождаться запроса время Y и если не дожидается - просыпается по таймауту и поняв что делать ему нефиг удаляет себя из пула
допустим в час пик колво потоков достигло 20 а затем пробили куранты все пошли обедать кроме трудоголика васи
вася старательно помылает серверу запросы
вася один а потоков 20
но поскольку работает механизм FIFO на каждый васин запрос будет просыпаться следующий поток, и таймаута ни один из них не дождется
вообщем нужен другой механизм необходимости удаления потока из пула, WAIT_TIMEOUT не подходит
Rouse_ (2006-02-01 15:53:00) [27]Может изменить логику?
1. Пришел запрос - свободных потоков нет - делаем новый, он запрашивает данные и начинает работать.
2. Поток отработал - ставим его на WaitXX (..., INFINITE);
3. Пришел запрос - делаем ReleaseSemaphore. Проснувшийся поток спрашивает свои данные и начинает их выполнять...
Если никто не проснулся, то пункт 1.
Digitman (2006-02-01 15:46:00) [28]
> Polevi © (01.02.06 15:32) [18]
> >Digitman © (01.02.06 15:29) [16]
> этот параметр равен колву клиентских запросов в очереди
Тогда вопрос - нашута обрабатывающему некий запрос потоку знать состояние очереди ? Не его это дело ..
Игорь Шевченко (2006-02-01 15:45:00) [29]Polevi © (01.02.06 15:41) [21]
Тебе хочется, чтобы на новый запрос просыпался поток, который последним обрабатывал клиентский запрос ? Ты извини за расспросы, я просто понять пытаюсь до конца.
Polevi (2006-02-01 15:41:00) [30]>Игорь Шевченко © (01.02.06 15:34) [20]
он его дождется если не будет больше запросов
собственно моя проблема в том, что если один клиент будет каждую секунду посылать запрос - за минуту последовательно проснуться 60 потоков с WAIT_OBJECT_0, до WAIT_TIMEOUT дело не дойдет
вот в случае с LIFO каждый раз бы просыпался поток который посденим вызвал Wait ф-ию а остальные 59 дождались бы таймаута и уничтожились
Игорь Шевченко (2006-02-01 15:34:00) [31]Polevi © (01.02.06 15:13) [14]
> оставшиеся потоки ждут след. вызова RS
Или таймаута ?
Я наверное не до конца понимаю, извини
Два рабочих потока ждут освобождения семафора с таймаутом.
Третий поток освободил семафор с ReleaseCount равным единице. Один из потоков проснулся с WAIT_OBJECT_0. Другой поток дождется таймаута ?
Rouse_ (2006-02-01 15:33:00) [32]А, ну собственно > Polevi © (01.02.06 15:13) [14]сам все рассказал :)
Polevi (2006-02-01 15:32:00) [33]>Digitman © (01.02.06 15:29) [16]
этот параметр равен колву клиентских запросов в очереди
Rouse_ (2006-02-01 15:32:00) [34]
> А не представляю я другое - каким образом кол-во "пробуждаемых"
> тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore()
> ..
По всей видимости у него сделано по такому принципу:
program Project1;
uses
Windows, Messages, SysUtils, gssocket;
const
THREAD_COUNT = 4;
var
hSemaphore: THandle;
hThread: array [0..THREAD_COUNT - 1] of THandle;
lpThreadId, lpPreviousCount: DWORD;
I: Integer;
procedure ThreadProc(lpParameter: Pointer); stdcall;
var
hThreadSemaphore: THandle;
begin
case WaitForSingleObject(hSemaphore, 100000) of
WAIT_OBJECT_0:
MessageBox(0, PChar('WAIT_OBJECT_0: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
WAIT_FAILED:
MessageBox(0, PChar('WAIT_FAILED: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
WAIT_TIMEOUT:
MessageBox(0, PChar('WAIT_TIMEOUT: ' + IntToStr(Integer(lpParameter))), nil, MB_OK);
end;
end;
begin
hSemaphore := CreateSemaphore(nil, 0, THREAD_COUNT, 'TestThreadSemaphore');
if hSemaphore = 0 then
RaiseLastOSError;
for I := 0 to THREAD_COUNT - 1 do
hThread[I] := CreateThread(nil, 0, @ThreadProc, Pointer(I), 0, lpThreadId);
lpPreviousCount := THREAD_COUNT;
Sleep(1000);
if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
RaiseLastOSError;
Sleep(2000);
if not ReleaseSemaphore(hSemaphore, 2, @lpPreviousCount) then
RaiseLastOSError;
Sleep(2000);
if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
RaiseLastOSError;
Sleep(2000);
end.
Тут наглядно видно. Создается 4 потока. 1 потока отпускаеться через секунду. Потом отпускаються еще два и потом еще один.
Кол-во потоков варьируеться в ReleaseSemaphore
Digitman (2006-02-01 15:29:00) [35]
> Polevi © (01.02.06 15:13) [14]
Спасибо. Это понятно.
Но непонятна твоя прикладная логика, относящаяся к "вызвал RS с параметром 2".
Почему не 3 ? Или не 1 ? Это же важно, согласись..
Eraser (2006-02-01 15:17:00) [36]по-моему по теме
Тут возникает интересный вопрос. Если несколько потоков ждет один объект ядра, какой из них пробудится при освобождении этого объекта? Официально Microsoft отвечает на этот вопрос так: "Алгоритм действует честно" Что это за алгоритм, Micro soft не говорит, потому что нс хочст связывать себя обязательствами всегда придер живаться именно этого алгоритма. Она утверждает лишь одно- если объект ожидает ся несколькими потоками, то всякий раз, когда этот объект переходит в свободное состояние, каждый из них получает шанс на пробуждение.
Таким образом, приоритет потока не имеет значения- поток с самым высоким приоритетом не обязательно первым захватит объект. Не получает преимущества и поток, который ждал дольше всех. Есть даже вероятность, что какой-то поток сумеет повторно захватить объект. Конечно, это было бы нечестно по отношению к другим потокам, и алгоритм пытается не допустить этого. Но никаких гарантий нет.
Рихтер
Polevi (2006-02-01 15:13:00) [37]напрямую зависит
счетчик=0
10 wait ф-ий ждут пока засигналит объект
я вызвал RS с параметром 2
объект засигналил
в 1 потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =1
объект продолжает сигналить
в 2потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =0
объект не сигналит
оставшиеся потоки ждут след. вызова RS
Digitman (2006-02-01 15:09:00) [38]
> Polevi © (01.02.06 15:00) [12]
> странно что я должен вам это обяъснять
Работу ф-ции мне не надо объяснять - я ее достаточно четко себе представляю.
А не представляю я другое - каким образом кол-во "пробуждаемых" тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore() ..
Polevi (2006-02-01 15:00:00) [39]The ReleaseSemaphore function increases the count of the specified semaphore object by a specified amount.
The state of a semaphore object is signaled when its count is greater than zero and nonsignaled when its count is equal to zero.
каждая ожидающая Wait ф-ия умньшит значение счетчика на 1
когда its count is equal to zero. потоки прекратят свое просыпание
странно что я должен вам это обяъснять если честно
Digitman (2006-02-01 14:34:00) [40]
> проснется столько сколько я укажу в ReleaseSemaphore
здесь, пожалуйста. подробнее ..