Big Cheese wrote:Насколько я понимаю, в данном случае подразумевается, что время удержания ресурса больше чем или сопоставимо со временем "прокрутки" спинлока, иначе у потока, крутящегося на другом ЦПУ есть шанс дождаться и захватить ресурс. С учетом того, что при конвое время удержания ресурса довольно мало по определению, при грамотно подобранном spin count есть шанс этот конвой уменьшить, разве нет?
Если я правильно понимаю Ваш вопрос - причина конвоя в том, код диспетчеризации не знает, что поток владеющий ресурсом лучше не вытеснять. А когда поток владеющий ресурсом вытеснен, он очевидно не не сможет его освободить пока он снова не получит ЦПУ. Понятно, что busy wait, в которые паларрельно / один за другим провалятся все остальные потоки, слабо зависит от соотношения времени удержания { которое в данном случае фактически равно времени, которое проходит, пока поток-владелец не получит снова ЦПУ и которое грубо ~ (SpinCount + время переключения контекста ) * количество потоков / количество ЦПУ } и SpinCount. Если, конечно не сделать SpinCount больше, чем это время. Что уж совсем бессмысленно.
tengiz wrote:К сожалению, в MSDN довольно невнятно (для меня) описано поведение планировщика в случае SwitchToThread. Вероятно, управление передается первому готовому к выполнению потоку, но что происходит с потоком, который добровольно отдал свой time slice - не понятно. Если он не ставится в конец очереди (что следует из вашего ответа), то что с ним происходит?
Это нигде не оговорено в публичной документации. Ставится он в конец очереди готовых или нет - неважно. Важно другое, что поток отдавший управление вызовом SwitchToThread не ставит себя в очередь ожидания события, тем самым устраняя причину конвоя.
Если под линейной очередью Вы имели в виду очередь потоков, ждущих на событии, то разве в Win32 ожидание реализовано в виде FIFO очереди?
Опять же - я не помню, чтобы в публичной документации эта деталь реализации явно оговаривалась. Но это тоже непринципиально (при условии, что очередь ведёт себя каким-то определённым образом, а не случайно) - главное, что если в очереди ожидающих освобождения кто-то есть, то вызов ResetEvent позволит немедленно захватить событие тому, кто первый стоит в очереди, поэтому текущий поток при повторной попытке захвата будет вытеснен и потеряет ЦПУ. Именно этого и старается избежать приведённый пример anti-convoy lock.