Составители:
Рубрика:
или /MDd (свойства проекта Configuration Properties|C/C++|Code
Generation|Runtime Library).
6.2.4.2. Работа с потоками
Наличие специальных потоко-безопасных версий библиотек требует
использования специальных функций для создания и завершения потоков,
принадлежащих не системному API, а библиотеке времени исполнения.
Так, вместо функций Win32 API CreateThread, ExitThread необходимо ис-
пользовать библиотечные функции _beginthread,
_endthread или _beginthreadex, _endthreadex. Это требование связано с тем,
что при создании нового потока необходимо, помимо выполнения опреде-
ленных действий по созданию потока со стороны операционной системы,
инициализировать специфичные структуры данных, обслуживающих по-
токо-безопасные версии функций библиотеки времени исполнения:
unsigned __stdcall ThreadProc( void *param )
{
/* вновь созданный поток будет выполнять эту функцию */
Sleep( 1000 );
delete[] (int*)param;
return 0;
/* завершение функции = завершение потока */
}
int main( void )
{
HANDLE hThread;
unsigned dwThread;
/* создаем новый поток */
hThread = (HANDLE)_beginthreadex
(NULL, 0, ThreadProc, new int [128], 0, &dwThread
);
/* код в этом месте может выполняться
одновременно с кодом функции потока ThreadProc,
планирование потоков осуществляется системой
*/
/* дождаться завершения созданного потока */
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
return 0;
}
Основы многозадачности
213
6.2.4. Основы использования потоков и волокон
Для реализации мультипрограммирования или мультипроцессирова-
ния на однотипных устройствах можно применять процессы, потоки и во-
локна. Разница между ними связана с возможностью обмена данными: ад-
ресное пространство процессов изолировано друг от друга, поэтому взаи-
модействие затруднено; потоки находятся в общем адресном пространст-
ве процесса и могут легко взаимодействовать друг с другом; волокна отча-
сти аналогичны потокам, но планирование волокон выполняется непо-
средственно приложением, а не операционной системой.
6.2.4.1. Потоко-безопасные и небезопасные функции
При реализации многопоточного приложения следует учитывать воз-
можные побочные эффекты. Наличие таких эффектов обусловлено реали-
зацией библиотеки времени исполнения: она содержит много функций
(в том числе внутренних, обеспечивающих семантику языка программиро-
вания), являющихся потоко-небезопасными. Примеры таких функций –
стандартная процедура strtok, операторы new и delete или функции
malloc, calloc, free и так далее. Фактически любая стандартная функция,
оперирующая статическими переменными, объектами или данными, мо-
жет являться потоко-небезопасной в силу того, что два потока могут полу-
чить одновременный конкурирующий доступ к этим данным и в итоге раз-
рушить их. Существует несколько подходов к решению этой проблемы:
• Можно предоставить потоко-безопасные аналоги (например,
strtok_r, являющийся в Linux потоко-безопасным аналогом
функции strtok).
• Можно переписать код всех потоко-небезопасных функций так,
чтобы они вместо глобальных объектов использовали локаль-
ную для потока память или синхронизировали доступ к общим
данным.
В Windows принят второй подход, однако, с некоторой оговоркой.
Потоко-безопасные версии функций более ресурсо- и время- емкие, чем
обычные. В итоге используется два вида библиотек: один для однопоточ-
ных приложений, другой для многопоточных. Следует отметить, что вы-
бор той или иной библиотеки определяется, как правило, свойствами про-
екта (параметрами компилятора), а вовсе не кодом приложения. Поэтому
при разработке многопотокового приложения важно проследить, чтобы
при компиляции использовалась правильная версия библиотеки, во избе-
жание возникновения трудно диагностируемых ошибок, проявляющихся
в самых разных и совершенно «невинных» на первый взгляд местах кода.
В случае Visual Studio однопоточные версии библиотек выбираются клю-
чами /ML или /MLd компилятора, а многопоточные ключами /MT, /MD, /MTd
212
CIL и системное программирование в Microsoft .NET
212 CIL и системное программирование в Microsoft .NET Основы многозадачности 213 6.2.4. Основы использования потоков и волокон или /MDd (свойства проекта Configuration Properties|C/C++|Code Generation|Runtime Library). Для реализации мультипрограммирования или мультипроцессирова- ния на однотипных устройствах можно применять процессы, потоки и во- 6.2.4.2. Работа с потоками локна. Разница между ними связана с возможностью обмена данными: ад- Наличие специальных потоко-безопасных версий библиотек требует ресное пространство процессов изолировано друг от друга, поэтому взаи- использования специальных функций для создания и завершения потоков, модействие затруднено; потоки находятся в общем адресном пространст- принадлежащих не системному API, а библиотеке времени исполнения. ве процесса и могут легко взаимодействовать друг с другом; волокна отча- Так, вместо функций Win32 API CreateThread, ExitThread необходимо ис- сти аналогичны потокам, но планирование волокон выполняется непо- пользовать библиотечные функции _beginthread, средственно приложением, а не операционной системой. _endthread или _beginthreadex, _endthreadex. Это требование связано с тем, что при создании нового потока необходимо, помимо выполнения опреде- 6.2.4.1. Потоко-безопасные и небезопасные функции ленных действий по созданию потока со стороны операционной системы, При реализации многопоточного приложения следует учитывать воз- инициализировать специфичные структуры данных, обслуживающих по- можные побочные эффекты. Наличие таких эффектов обусловлено реали- токо-безопасные версии функций библиотеки времени исполнения: зацией библиотеки времени исполнения: она содержит много функций (в том числе внутренних, обеспечивающих семантику языка программиро- unsigned __stdcall ThreadProc( void *param ) вания), являющихся потоко-небезопасными. Примеры таких функций – { стандартная процедура strtok, операторы new и delete или функции /* вновь созданный поток будет выполнять эту функцию */ malloc, calloc, free и так далее. Фактически любая стандартная функция, Sleep( 1000 ); оперирующая статическими переменными, объектами или данными, мо- delete[] (int*)param; жет являться потоко-небезопасной в силу того, что два потока могут полу- return 0; чить одновременный конкурирующий доступ к этим данным и в итоге раз- /* завершение функции = завершение потока */ рушить их. Существует несколько подходов к решению этой проблемы: } • Можно предоставить потоко-безопасные аналоги (например, strtok_r, являющийся в Linux потоко-безопасным аналогом int main( void ) функции strtok). { • Можно переписать код всех потоко-небезопасных функций так, HANDLE hThread; чтобы они вместо глобальных объектов использовали локаль- unsigned dwThread; ную для потока память или синхронизировали доступ к общим /* создаем новый поток */ данным. hThread = (HANDLE)_beginthreadex В Windows принят второй подход, однако, с некоторой оговоркой. (NULL, 0, ThreadProc, new int [128], 0, &dwThread Потоко-безопасные версии функций более ресурсо- и время- емкие, чем ); обычные. В итоге используется два вида библиотек: один для однопоточ- /* код в этом месте может выполняться ных приложений, другой для многопоточных. Следует отметить, что вы- одновременно с кодом функции потока ThreadProc, бор той или иной библиотеки определяется, как правило, свойствами про- планирование потоков осуществляется системой екта (параметрами компилятора), а вовсе не кодом приложения. Поэтому */ при разработке многопотокового приложения важно проследить, чтобы /* дождаться завершения созданного потока */ при компиляции использовалась правильная версия библиотеки, во избе- WaitForSingleObject( hThread, INFINITE ); жание возникновения трудно диагностируемых ошибок, проявляющихся CloseHandle( hThread ); в самых разных и совершенно «невинных» на первый взгляд местах кода. return 0; В случае Visual Studio однопоточные версии библиотек выбираются клю- } чами /ML или /MLd компилятора, а многопоточные ключами /MT, /MD, /MTd
Страницы
- « первая
- ‹ предыдущая
- …
- 111
- 112
- 113
- 114
- 115
- …
- следующая ›
- последняя »