У меня создаётся несколько потоков (п1,п2,п3). Иногда случаются моменты, когда несколько потоков пытаются захватить закрытый объект синхронизации (Mutex например). Так, вот, есть ли какой-либо метод в операционной системе, что бы, при переходе Мутекса в сигнальное состояние, потокам передавалось управление в той последовательности в какой они захватывали объект синхронизации?
наверное, нет: когда-то я писал самработу и запустил около десятка экземпляров программ, которые пытались захватить один мьютекс, так хватали только первые два, изредка - третий. остальные - отдыхали. так что я понял, что они вызываются каждый раз по списку с начала. правда, платформа была: win95/486dlc-40, а проги отпускали мьютекс и сразу же пытались его захватить.
Ох, философы устали за неделю! ща одна проблема - машину рядом с домом поставить или в гараже хрен знает где?.. а вдруг завтра на морозе не заведется! может, топик создать - насоветуют чего
Кстати говоря на 2000 засуне и старше сделано распределение мьютекса между потоками таким образом, чтобы избежать вот этой проблемы:
> Точный механизм микробы не описывают, но там что-то вроде рандома с искуственным интелектом Браво! В цитатник..
Код (Text): „потокам передавалось управление в той последовательности в какой они захватывали объект синхронизации?“ Напиши чуть яснее, боюсь ошибиться. Да. Криво. Должно быть так: „потокам передавалось управление в той последовательности в какой они пытаются захватить объект синхронизации?“ То есть, владельцем мутекса может быть только один. А остальные "спят". Как только освобождается мутекс, один из потоков просыпается и захватывает мутекс, только проснуться должен тот поток который, наткнувшись на закрытый мутекс, "уснул" первым.
2 Trashy Я думаю это реально сделать не средставми системы (поскольку таковых нет), но вручную. Например заводишь глобальную переменную и т.п. А для чего тебе это надо?
Trashy вот, набросал кой чего - на большее времени нет Вариант для потоков одного процесса с кольцевой очередью на 256 потоков. Используется два мьютекса - один для дела, и один - для доступа к очереди. Количество потоков не проверяется - при превышении могут появиться потоки, уснувшие навечно - в этом случае или вводится контроль, или расширяется очередь. В случае разных процессов можно использовать memory mapped file для очереди. для данного механизма наследование хэндлов обязательно! смысл в том, что текущий владелец мьютекса освобождает его, если пуста очередь ожидающих потоков, иначе он "будит" первый из них, отдавая ему хэндл неосвобожденного мьютекса. таким образом все желающие завладеть мьютексом вынуждены становиться в очередь, пока она непуста... Код (Text): .data? ; общие данные queue dd 256 dup(?) ; индивидуальные данные для потока pid dd ? hMutex_q dd ? hMutex_m dd ? .data ; общие данные q_in db 0 q_out db 0 .code ... @@: invoke OpenMutex,... ; попытка захватить главный мьютекс без ожидания test eax,eax jnz @F invoke OpenMutex,... ; захват мьютекса доступа к очереди с ожиданием mov hMutex_q,eax movzx eax,q_in mov ecx,pid lea eax,queue[eax*4] mov [eax],ecx ; записываем пид данного потока в очередь inc q_in ; увеличиваем указатель очереди для записи push eax invoke ReleaseMutex,hMutex_q ; отпускаем мьютекс очереди перед сном invoke SuspendThread,pid ; останавливаем данный поток pop eax mov eax,[eax] ; извлекаем хэндл мьютекса @@: ;-------------------------- главный мьютекс захвачен! mov hMutex_m,eax . . . invoke OpenMutex,... ; захват мьютекса доступа к очереди с ожиданием mov hMutex_q,eax movzx eax,q_out ; пуста ли очередь? cmp al,q_in je @F ; если да - то вперед lea eax,queue[eax*4] ; получаем адрес в очереди mov ecx,hMutex_m xchg ecx,[eax] ; заменяем в очереди пид потока на хэндл главного мьютекса inc q_out ; увеличиваем указатель очереди для чтения invoke ResumeThread,ecx ; запускаем поток первый из очереди jmp d_exit @@: invoke ReleaseMutex,hMutex_m ; отпускаем главный мьютекс d_exit: invoke ReleaseMutex,hMutex_q ; отпускаем мьютекс очереди ...
Если первый поток захватит главный Mutex когда очередь пуста, а потом вдруг уснёт после выполнения cmp al,q_in и в этот момент второй поток попытается добавить себя в очередь, то второй поток уснёт, а кто-то другой сможет захватит главный Mutex вне очереди.
NoName А, заводить глобальную переменную, не очень красиво. Это поток просыпается(захватывает объект), смотрит его ли очередь и если не его - освобождает объект и Sleep(0);... Это просто, но это переключение контекстов. А если потоков 10! Или двадцать! Или... Да хер его знает сколько пользователей приконнектится может... Это сколько же Sleep'ов произойдёт пока нужный поток не подключится? Причём вызвав Sleep я не могу вызвать WaitForSingleObject, так как мутекс открыт. И так придётся вызывать Sleep до тех пор, пока не поймаю нужный поток! А есть метод получения количества спящих объектов на мутексе? Есть гденить инфа о практическом применений extended alertable function (SleepEx или WaitForSingleObjectEx)? У меня просто работа с асинхронным-IO связана. Зачем мне это? Что бы знать как это всё работает. Уже почти всего Рихтера перерыл, а ответа найти не могу.
нужно писать диспетчер, работающий как мьютекс, но так как надо. механизм, который я привел, имеет сущ. недостаток - если текущий поток скоропостижно отбросит копыта, то вся очередь будет спокойно спать до завершения процесса (хотя и на этот случай мысли наклевываются, но пока неясные) sleep - не очень хороший вариант - нужна четкая остановка и запуск потоков согласно очереди. насчет инфы: не вся полная и ясная - все нужно пробовать.