thread_programming.pptx
- Количество слайдов: 40
Практика по программированию Юдин Юрий Борисович Весна 2013 1
Лекция Многопоточное программирование 2
Процессы и потоки Процесс Память Адресное пространство Глобальные данные CPU CPU Куча 1 3 1 2 3 2 1 2 3 3 2 2 2 1 1 1 3 3 3 2 2 Потоки Код Код Много статей на английском: http: //citeseer. ist. psu. edu/ http: //citeseer. nj. nec. com/directory. html http: //www. iop. org/EJ/toc/09671846/2/1 Internet Parallel Computing Archive http: //wotug. ukc. ac. uk/parallel/ Много электронных учебников: http: //lib. krgtu. ru/ebibl/links 2/ http: //softsearch. ru/catalog/desktop/ed ucation/how_much 100/ Сборка инфы по архитектуре: http: //crestone. uccs. edu/~Comp. Arch/ Useful documents http: //mindhack. cebuano. org/ ftp: // Много документации по программированию и т. п. http: //linux. yaroslavl. ru/docs/ http: //www. rushelp. com/ http: //www. helloworld. ru/ Есть кой-чего про ассемблер, архитектуру http: //www. kolasc. net. ru/cdo/index. htm l Энциклопедия по всему подряд, включая общую информацию о микропроцессорах http: //www. campusprogram. com/refere nce/en/wikipedia/x/x 86. html Книги по математике http: //www. mccme. ru/free-books/ Неготовый сайт по ASM 386 - P 4 http: //sasm. narod. ru/ Форум по процессорам AMD-INTEL 32 -64 http: //num-meth. srcc. msu. ru/ Parallel Programming Systems: COPS, Enterprise, . . . http: //www. cs. ualberta. ca/~systems/ Fortran reference http: //h 18009. www 1. hp. com/fortran/docs/l rm/dflrm. htm#book-toc Compaq C Compiler Programmer's Guide ftp: //ftp. compaq. com/pub/products/CCXX/linux/compaq_c/docs/ccc/Program mers_Guide/TITLE. HTM Вообще по Альфе много чего: ftp: //ftp. compaq. com/pub/products Научная литература в Интернет http: //www. scintific. narod. ru/literature. htm http: //psi-logic. narod. ru http: //www. lowlevel. ru/ Стек
Процессы и потоки Преимущества потоков: l Быстрое переключение между потоками l Простая организация взаимодействия – общая память Недостатки потоков: l Некорректное использование данных одним потоком отражается на всех других l Необходимость в синхронизации при доступе к общим данным l Используемые библиотеки должны поддерживать многопоточность
Разработка многопоточной программы Потоки: l Решают задачу над общими данными l Взаимодействуют через общую память l Упорядочивают взаимодействие путем синхронизации Ключ к созданию корректной параллельной программы – правильная синхронизация процессов и потоков.
Средства создания многопоточных программ l Библиотеки потоков ¡Posix Threads ¡Windows Threads ¡… l Open. MP l Распараллеливающие компиляторы
Разработка многопоточной программы (Win. API, Pthreads) l Все потоки описываются в виде отдельных функций l Первичный поток выполняет функцию main l Новые потоки могут запускаться выполняющимися потоками
Управление потоками l Создание потока (Create. Thread) l Завершение потока (exit or Terminate. Thread) l Приостановка потока (Suspend. Thread) l Возобновление потока (Resume. Thread) l Переключение между потоками (Switch. To. Thread) Не завершайте поток вручную, пусть завершится функция потока.
Win 32* «HANDLE» – тип данных для обращения к любому объекту Windows ¡К каждому объекту в Windows можно обратиться с помощью переменной типа «HANDLE» l Указатель на объекты ядра l Потоки, процессы, файлы, события, мьютексы, семафоры, и т. д. l Функция создания объекта возвращает «HANDLE» ¡Управление объектом можно осуществлять через его «HANDLE» ¡Напрямую обращаться к объектам нельзя 9
Создание потока Win 32* HANDLE Create. Thread( LPSECURITY_ATTRIBUTES Thread. Attributes, DWORD Stack. Size, LPTHREAD_START_ROUTINE Start. Address, LPVOID Parameter, DWORD Creation. Flags, LPDWORD Thread. ID ); 10
Create. Thread(): первый параметр – «атрибуты безопасности» Thread. Attributes l Каждый объект ядра имеет атрибуты безопасности l Первый параметр в Create. Thread() позволяет программисту определить атрибуты безопасности для потока l Система защиты объектов Windows определяет совокупности процессов с разрешенным или запрещенным доступом к данным объектам l Значение «NULL» устанавливает значения атрибутов безопасности «по умолчанию» 11
Create. Thread(): второй параметр –объем стека потока - Stacksize l Параметр Stacksize позволяет пользователю определить размер стека потока l Значение ‘ 0’ позволяет установить объем стека «по умолчанию» , равное одному мегабайту 12
Create. Thread(): третий параметр – имя функции, с выполнения которой поток начнет работу - Start. Address l Третий параметр, Start. Address – это имя функции l В дальнейшем эту функцию будем называть «функция потока» , «потоковая функция» , «функция для многопоточного выполнения» l С выполнения функции с этим именем поток и начнет свою работу l Это функция с глобальной видимостью, объявляемая как DWORD WINAPI. 13
Create. Thread(): четвертый параметр - Parameter l Потоковой функции требуется только один параметр типа LPVOID ( «указатель на VOID» ). Значение этого параметра для потока может быть установлено с помощью четвертого параметра. l Если потоковой функции требуется больше, чем одно значение, можно инкапсулировать их в одну структуру, которую и передать в качестве четвертого параметра. l При этом самым первым действием, выполненным в потоковой функции, должна быть декомпозиция этой структуры на отдельные компонентные части. 14
Create. Thread(): пятый параметр – «режим старта» Creation. Flags l Creation. Flags позволяет определить «режим старта» потока, который создан, но выполнение которого «приостановлено» . l «По умолчанию» ( для этого нужно установить значение параметра, равное ‘ 0’) работа потока начинается сразу, как только он создается системой. 15
Create. Thread(): шестой параметр – Thread. Id l Thread. Id – параметр «уникальности» , который обеспечивает то, что каждое потоковое задание выполняется своим потоком l может использоваться повторно до тех пор, пока данный поток существует. 16
Если создать поток не удалось. . . l Если выполнение Create. Thread() не завершилось созданием потока, будет возвращено «FALSE» l Причина «неудачи» может быть установлена с помощью вызова Get. Last. Error(). l Get. Last. Error()- РЕКОМЕНДУЕТСЯ ВЫПОЛНЯТЬ ВСЕГДА ДЛЯ ЛЮБОГО ОШИБОЧНОГО КОДА 17
LPTHREAD_START_ROUTINE Start. Address – третий параметр в Create. Thread() – подробнее. . . l Create. Thread() ожидает указателя на глобальную функцию ¡Тип возвращаемого этой функцией значения DWORD ¡Вызывает стандартные WINAPI ¡Функция обладает единственным формальным параметром типа LPVOID (void *) – «указатель на void» - четвертый параметр в Create. Thread() DWORD WINAPI My. Thread. Start(LPVOID p); l Поток начинает работу с выполнения этой функции 18
Способы передачи данных между потоками l Передача параметров в функцию потока (LPVOID param) l Передача указателя на объект через параметр функции потока l Работа с глобальными переменными
Синхронизация потоков Необходима при: l Совместном использовании ресурса (атомарные операции) l Уведомлении потоков о некотором событии
Проблема поставщик-потребитель
Проблема поставщик-потребитель
Проблема поставщик-потребитель
Средства синхронизации потоков Windows Threads Posix Threads Переменные состояния Критические секции Мьютексы События Условные переменные Семафоры
Средства синхронизации потоков в Windows В пользовательском режиме: l Переменные состояния l Критические секции С использованием объектов ядра: l Процессы, потоки l События l Семафоры l Мьютексы l Таймеры
Немного о Wait. For. Single. Object ¡ Wait. For. Single. Object будет блокировать завершение других потоков, пока данный поток не закончит свою работу (handle is signaled); ¡ Второй параметр – это временной предел для ожидания. ¡ Если время ожидания превышено, код становится доступен для выполнения другими потоками, независимо от того, в каком состоянии находится HANDLE. ¡ Чтобы установить условием окончания ожидания завершение работы потока (handle signaled), нужно установить время ожидания «бесконечность» INFINITE (определенное значение константы ). ¡ Любое другое значение временного предела приведет к ошибке. Нужно проверить код ошибки, чтобы установить причину завершения работы функции • Wait. For. Single. Object может быть применен не только для потока, но и для «события» , «мьютекса» и т. д. 26
Критические секции l Используются для взаимоисключающего доступа к ресурсу l Обеспечивают атомарное исполнение участка кода l Операции: ¡Вход в критическую секцию (Enter. Critical. Section) ¡Выход из критической секции (Leave. Critical. Section) l В начале ожидания используют спинблокировку Initialize. Critical. Section. And. Spin. Count(&Critical. Section, 0 x 00000400) l При длительном ожидании используют мьютекс
Критические секции Initialize. Critical. Section(&g_cs); for (int i = 0; i < num. Threads; i++) { t. Num[i] = i; h. Thread[i] = Create. Thread(NULL, 0, thread. Func, &t. Num[i], 0, NULL); } Wait. For. Multiple. Objects(num. Threads, h. Thread, TRUE, INFINITE); Delete. Critical. Section(&g_cs);
Condition Variables Не поддерживаются на Win. XP, Win Server 2003 CONDITION_VARIABLE Buffer. Not. Empty; CONDITION_VARIABLE Buffer. Not. Full; Sleep. Condition. Variable. CS (&Buffer. Not. Full, &Buffer. Lock, INFINITE); Wake. Condition. Variable (&Buffer. Not. Empty);
Объекты ядра l Объект может быть «занят» или «свободен» l Операции: ¡Создание объекта ядра ¡Получение доступа к существующему объекту ядра ¡Удаление объекта ядра ¡…
Синхронизация с помощью объектов ядра l Синхронизация осуществляется с помощью wait-функций, ожидающих освобождения одного или нескольких объектов: ¡Wait. For. Single. Object ¡Wait. For. Multiple. Objects ¡…
События l Используются для уведомления потоков о некотором событии l Операции ¡Перевести в свободное состояние ¡Перевести в занятое состояние ¡Ждать освобождения (wait-функция) l Типы событий ¡С автосбросом: просыпается 1 ожидающий поток ¡Со сбросом вручную: просыпаются все ожидающие потоки
Мьютекс (Win 32* Mutexes) ¡ Объект ядра, Create. Mutex(…) возвращает ”HANDLE” мьютекса ¡ Используется «Wait. For. Single. Object» для «закрытия на замок» или «блокирования» мьютекса ¡ Если мьютекс не заблокирован, “HANDLE” мьютекса в состоянии «сигнализирует» (“Signaled” или «свободен» [2]), ¡ При выполнении функции «Wait. For. Single. Object» , мьютекс оказывается захваченным одним из потоков и переходит в состояние “non-signaled” ( «занят» [2]) ¡ Блокировка мьютекса снимается с помощью операции Release. Mutex(…) ¡ Create. Mutex(…) //создать новый мьютекс ¡ Wait. For. Single. Object // «ждать и не подпускать» (wait & lock) ¡ Release. Mutex(…) // освободить (unlock) l Используется для координации действий множества процессов 33
Мьютексы dw. Wait. Result = Wait. For. Single. Object( gh. Mutex, // handle to mutex INFINITE); // no time-out interval switch (dw. Wait. Result) { // The thread got ownership of the mutex case WAIT_OBJECT_0: __try { // TODO: Write to the buffer printf("Thread %d writing to buffer. . . n", Get. Current. Thread. Id()); dw. Count++; } __finally { // Release ownership of the mutex object if (! Release. Mutex(gh. Mutex)) { // Handle error. } } break; // The thread got ownership of an abandoned mutex // The buffer is in an indeterminate state case WAIT_ABANDONED: return FALSE; }
Семафоры - Win 32* Semaphores l Объекты синхронизации, использующие счетчик l Этот счетчик представляет число доступных ресурсов ¡ Ввел и сформулировал Edsger Dijkstra (1968) l Две операции для семафора ¡ Ждать [P(s)]: l Поток ждет, пока s > 0, при этом s уменьшается s = s - 1 ¡ Одному продолжить [V(s)]: s = s + 1 l Семафор «свободен» (signaled) (объекты синхронизации Windows 2000, [2]), когда «показания счетчика» доходят до нуля l Семафор “is in signaled state” ( «свободен» , по переводу [2]), если s>0 ([3], Win 32*) 35
Создание семафора (Win 32* Semaphore) HANDLE Create. Semaphore( LPSECURITY_ATTRIBUTES lp. Event. Attributes, LONG l. Sem. Initial, //Начальное значение счетчика LONG l. Sem. Max, //Максимальное значение счетчика LPCSTR lp. Sem. Name); // l Значение l. Sem. Max должно быть больше или равно 1 l Значение l. Sem. Initial должно быть ¡ Больше или равно 0, ¡ Меньше или равно l. Sem. Max, и ¡ Не может выйти за границы диапазона 36
Операции ждать – продолжить (Wait and Post) l Wait. For. Single. Object ( «ожидание одного» ) – на семафоре ¡ Пока не будет == 0, поток ждет ¡ Уменьшает счетчик на 1, пока он положителен Увеличение переменной семафора – операция «продолжить» (Post operation) BOOL Release. Semaphore( HANDLE h. Semaphore, LONG c. Release. Count, LPLONG lp. Previous. Count ); ¡ Увеличивает переменную счетчика посредством c. Release. Count ¡ возвращает предыдущее значение через lp. Previous. Count 37
Предназначение семафоров l Управлять доступом к структурам данных конечного размера ¡ Queues, stacks, deques ¡ Счетчик применяется для нумерации доступных элементов l Управлять доступом к конечному числу ресурсов ¡ File descriptors, tape drives… l Контролировать число активных потоков в области l Бинарный семафор [0, 1] может работать как мьютекс 38
Таймеры l Используются для уведомления о наступлении определенного времени l Операции ¡Установить таймер ¡Ждать срабатывания таймера ¡Сбросить таймер http: //msdn. microsoft. com/enus/library/windows/desktop/ms 687008%28 v=vs. 85%29. asp x
Спасибо! Вопросы? 40
thread_programming.pptx