Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
os_a_win.doc
Скачиваний:
15
Добавлен:
17.11.2019
Размер:
715.26 Кб
Скачать

Потоки и библиотека языка с

При работе на языке C использовать функцию CreateThread для создания потока не рекомендуется. Связано это с тем, что стандартная библиотека языка С разрабатывалась во времена, когда многопоточное программирование еще не использовалось и в ней активно использовались глобальные переменные. В результате некоторые из ее функций не могут использоваться в многопоточной среде (такие функции называются нереентерабельными). Для того чтобы обойти это ограничение, современные библиотеки языка С создают специальную область данных, привязанную к каждому потоку. Чтобы дать возможность библиотеке создать (а затем и освободить) эту область данных мы должны вместо функций CreateThread и ExitThread использовать соответственно _beginthreadex и _endthreadex:

uintptr_t _beginthreadex(

void *security,

unsigned stack_size,

unsigned ( __stdcall *start_address )( void * ),

void *arglist,

unsigned initflag,

unsigned *thrdaddr

);

void _endthreadex(

unsigned retval

);

Операции с потоками

Для выполнения операций с потоками, прежде всего, необходимо получить идентификатор потока. Его мы можем получить от функции CreateProcess, CreateThread или GetCurrentThread, которая возвращает дескриптор текущего потока. Наряду с дескриптором каждый поток имеет общесистемный идентификатор, который мы можем узнать, вызвав функцию GetCurrentThreadId. Получить доступ к другому потоку, зная его идентификатор можно с помощью функции OpenThread:

HANDLE OpenThread(

DWORD dwDesiredAccess, // access right

BOOL bInheritHandle, // handle inheritance option

DWORD dwThreadId // thread identifier

);

Одно из основных действий, которое мы можем производить с потоком, это приостановление и возобновление его работы. При приостановлении поток переводится в состояние ожидания и не использует процессорное время. Как мы помним, поток можно создать в приостановленном состоянии, если передать функции создания потока флаг CREATE_SUSPENDED. Для того чтобы сделать приостановленный поток активным (планируемым) необходимо вызвать функцию ResumeThread:

DWORD ResumeThread(

HANDLE hThread // handle to thread

);

Мы также можем в любой момент приостановить выполнение потока, вызвав функцию SuspendThread:

DWORD SuspendThread(

HANDLE hThread // handle to thread

);

Любой поток может перевести себя на некоторое время в приостановленное состояние, вызвав функцию Sleep:

VOID Sleep(

DWORD dwMilliseconds // sleep time

);

Параметр dwMilliseconds задает время в миллисекундах, на которое поток «заснет». Эту функцию нужно использовать в случаях, когда необходимо задержать выполнение потока на некоторое время. В однозадачных системах для этого обычно делают цикл, который проверяет системное время и сравнивает его с начальным моментом. Однако в многозадачной системе такой вариант не приемлем – подобный цикл будет напрасно расходовать все процессорное время, снижая работоспособность системы. В это же время функция Sleep позволяет решить ту же задачу, не загружая процессор.

Рекомендуется использовать Sleep и в том случае, если все-таки не удалось обойтись без проверки какого-либо условия в цикле. В этом случае помещенная внутрь цикла функция Sleep c небольшим интервалом позволит снизить нагрузку на процессор. Впрочем, это все-таки не очень хороший вариант и лучше постараться организовать ожидание с помощью объектов синхронизации и Wait-функций, которые мы рассмотрим далее.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]