Составители:
Рубрика:
Есть частный случай применения функции Sleep – при задании ин-
тервала 0 вызов функции просто приводит к срабатыванию планировщи-
ка и, при наличии других готовых потоков, к их активации. Аналогичного
эффекта можно добиться, применяя функцию SwitchToThread, вызываю-
щую перепланирование потоков.
Поток может быть создан в приостановленном (suspended) состоянии с
помощью задания специального флага CREATE_SUSPENDED при вызове функ-
ций _beginthreadex или CreateThread, а также переведен в это состояние
(функция SuspendThread) или, наоборот, пробужден с помощью функции
ResumeThread.
6.2.4.3. Работа с волокнами
Работа с волокнами в приложении в чем-то сложнее, в чем-то проще.
Сложнее, потому что необходимо реализовать собственный планировщик
волокон. Сложность разработки планировщика резко возрастает при
необходимости синхронизации волокон – стандартные средства синхро-
низации Windows переводят в режим ожидания поток целиком, даже если
он должен планировать множество волокон. Проще, потому что все во-
локна могут разделять один поток – в этом случае легко избежать проблем
конкурирующего доступа к данным и можно применять любую библиоте-
ку времени исполнения, в том числе потоко-небезопасную.
При работе с волокнами используется функция ConvertThreadToFiber
для предварительного создания необходимых операционной системе струк-
тур данных. Функция ConvertFiberToThread выполняет обратную задачу и
уничтожает выделенные данные. После того как необходимые структуры со-
зданы (поток «превращен» в волокно), появляется возможность создавать но-
вые волокна (CreateFiber), удалять существующие (DeleteFiber) и планиро-
вать их исполнение (SwitchToFiber).
Приведем пример применения двух рабочих волокон, выполняющих
целевую функцию, и одного управляющего, удаляющего рабочие волокна
по их завершении.
Функция main превращает текущий поток в волокно (инициализация
внутренних структур данных для работы с волокнами), затем создает рабо-
чие волокна и организует цикл, в котором ожидает их завершения и удаля-
ет. Цикл завершается тогда, когда все рабочие волокна удалены, после че-
го функция main принимает меры к корректному завершению работы с во-
локнами.
Собственно целевая функция FiberProc эпизодически вызывает
функцию SwitchToFiber для переключения выполняемого волокна. В дан-
ном примере для определения нового волокна, подлежащего исполнению,
реализован простейший планировщик (функция schedule, инкапсулирую-
щая вызов функции SwitchToFiber).
Основы многозадачности
215
В данном примере можно было бы создавать поток не вызовом функ-
ции _beginthreadex (или _beginthread), а вызовом функции API
CreateThread. Но при незначительном усложнении примера, скажем, соз-
дании не одного, а двух потоков, уже было бы возможно возникновение
ошибки при одновременном обращении к операторам new или delete в
разных потоках (причем именно «возможно», так как ничтожные времен-
ные задержки могут изменить поведение потоков – это крайне осложняет
выявление таких ошибок). Применение функций библиотеки времени ис-
полнения для создания потоков решает эту проблему.
Windows содержит достаточно богатый набор функций для управле-
ния потоками, включающий функции создания и завершения потоков
(функции API CreateThread, ExitThread, TerminateThread и их «обертки» в
библиотеке времени исполнения _beginthread, _endthread, _beginthreadex
и _endthreadex).
Функция Sleep(DWORD dwMilliseconds) может переводить поток в
«спячку» на заданное время. Продолжительность задается с точностью до
кванта работы планировщика, то есть не лучше, чем 10-15 мс, несмотря на
то, что при вызове функции задать можно до 1 мс. Измерение времени ре-
альной паузы, заданной, например, вызовом Sleep(1), позволяет получить
косвенную информацию о работе планировщика.
В Windows существует интересная особенность, связанная с работой
планировщика и измерением интервалов времени. Система предоставля-
ет три способа измерения интервалов:
• таймер низкого разрешения, основанный на квантах планиров-
щика (GetTickCount);
• «мультимедийный», с разрешением до 1 мс (timeGetTime,
timeBeginPeriod и пр.);
• высокоточный, использующий счетчик тактов процессора и с
разрешением ощутимо лучше микросекунды на современных
процессорах (QueryPerformanceCounter,
QueryPerformanceFrequency).
Обычно мультимедийный таймер работает с разрешением от 1-5 мс и ху-
же (зависит от аппаратуры), однако функция timeBeginPeriod позволяет изме-
нить разрешение вплоть до 1 мс. Если стандартное разрешение мультимедий-
ного таймера на данном компьютере хуже 5-10 мс, то у функции
timeBeginPeriod есть побочный эффект – улучшение разрешения повлияет на
работу планировщика во всей системе, а не только в процессе, вызвавшем эту
функцию. В результате, если один процесс повысит разрешение мультимедий-
ного таймера, то функция Sleep также получит возможность задавать интерва-
лы вплоть до 1 мс и эффект наблюдается даже в других процессах. Если муль-
тимедийный таймер на данной аппаратуре стандартно работает с разрешением
порядка 1 мс, то такого влияния на планировщик не наблюдается.
214
CIL и системное программирование в Microsoft .NET
214 CIL и системное программирование в Microsoft .NET Основы многозадачности 215 В данном примере можно было бы создавать поток не вызовом функ- Есть частный случай применения функции Sleep – при задании ин- ции _beginthreadex (или _beginthread), а вызовом функции API тервала 0 вызов функции просто приводит к срабатыванию планировщи- CreateThread. Но при незначительном усложнении примера, скажем, соз- ка и, при наличии других готовых потоков, к их активации. Аналогичного дании не одного, а двух потоков, уже было бы возможно возникновение эффекта можно добиться, применяя функцию SwitchToThread, вызываю- ошибки при одновременном обращении к операторам new или delete в щую перепланирование потоков. разных потоках (причем именно «возможно», так как ничтожные времен- Поток может быть создан в приостановленном (suspended) состоянии с ные задержки могут изменить поведение потоков – это крайне осложняет помощью задания специального флага CREATE_SUSPENDED при вызове функ- выявление таких ошибок). Применение функций библиотеки времени ис- ций _beginthreadex или CreateThread, а также переведен в это состояние полнения для создания потоков решает эту проблему. (функция SuspendThread) или, наоборот, пробужден с помощью функции Windows содержит достаточно богатый набор функций для управле- ResumeThread. ния потоками, включающий функции создания и завершения потоков (функции API CreateThread, ExitThread, TerminateThread и их «обертки» в 6.2.4.3. Работа с волокнами библиотеке времени исполнения _beginthread, _endthread, _beginthreadex Работа с волокнами в приложении в чем-то сложнее, в чем-то проще. и _endthreadex). Сложнее, потому что необходимо реализовать собственный планировщик Функция Sleep(DWORD dwMilliseconds) может переводить поток в волокон. Сложность разработки планировщика резко возрастает при «спячку» на заданное время. Продолжительность задается с точностью до необходимости синхронизации волокон – стандартные средства синхро- кванта работы планировщика, то есть не лучше, чем 10-15 мс, несмотря на низации Windows переводят в режим ожидания поток целиком, даже если то, что при вызове функции задать можно до 1 мс. Измерение времени ре- он должен планировать множество волокон. Проще, потому что все во- альной паузы, заданной, например, вызовом Sleep(1), позволяет получить локна могут разделять один поток – в этом случае легко избежать проблем косвенную информацию о работе планировщика. конкурирующего доступа к данным и можно применять любую библиоте- В Windows существует интересная особенность, связанная с работой ку времени исполнения, в том числе потоко-небезопасную. планировщика и измерением интервалов времени. Система предоставля- При работе с волокнами используется функция ConvertThreadToFiber ет три способа измерения интервалов: для предварительного создания необходимых операционной системе струк- • таймер низкого разрешения, основанный на квантах планиров- тур данных. Функция ConvertFiberToThread выполняет обратную задачу и щика (GetTickCount); уничтожает выделенные данные. После того как необходимые структуры со- • «мультимедийный», с разрешением до 1 мс (timeGetTime, зданы (поток «превращен» в волокно), появляется возможность создавать но- timeBeginPeriod и пр.); вые волокна (CreateFiber), удалять существующие (DeleteFiber) и планиро- • высокоточный, использующий счетчик тактов процессора и с вать их исполнение (SwitchToFiber). разрешением ощутимо лучше микросекунды на современных Приведем пример применения двух рабочих волокон, выполняющих процессорах (QueryPerformanceCounter, целевую функцию, и одного управляющего, удаляющего рабочие волокна QueryPerformanceFrequency). по их завершении. Обычно мультимедийный таймер работает с разрешением от 1-5 мс и ху- Функция main превращает текущий поток в волокно (инициализация же (зависит от аппаратуры), однако функция timeBeginPeriod позволяет изме- внутренних структур данных для работы с волокнами), затем создает рабо- нить разрешение вплоть до 1 мс. Если стандартное разрешение мультимедий- чие волокна и организует цикл, в котором ожидает их завершения и удаля- ного таймера на данном компьютере хуже 5-10 мс, то у функции ет. Цикл завершается тогда, когда все рабочие волокна удалены, после че- timeBeginPeriod есть побочный эффект – улучшение разрешения повлияет на го функция main принимает меры к корректному завершению работы с во- работу планировщика во всей системе, а не только в процессе, вызвавшем эту локнами. функцию. В результате, если один процесс повысит разрешение мультимедий- Собственно целевая функция FiberProc эпизодически вызывает ного таймера, то функция Sleep также получит возможность задавать интерва- функцию SwitchToFiber для переключения выполняемого волокна. В дан- лы вплоть до 1 мс и эффект наблюдается даже в других процессах. Если муль- ном примере для определения нового волокна, подлежащего исполнению, тимедийный таймер на данной аппаратуре стандартно работает с разрешением реализован простейший планировщик (функция schedule, инкапсулирую- порядка 1 мс, то такого влияния на планировщик не наблюдается. щая вызов функции SwitchToFiber).
Страницы
- « первая
- ‹ предыдущая
- …
- 112
- 113
- 114
- 115
- 116
- …
- следующая ›
- последняя »