МО ВВС ИВМ и МГ СО РАН POSIX Threads Городничев Максим Александрович Что такое POSIX Threads Threads = поток = нить POSIX = Portable Operating System Interface for UNIX = Интерфейс переносимой операционной системы UNIX набор стандартов, описывающих интерфейсы между операционной системой и прикладной программой. Многопоточное программирование • Используется для создания параллельных программ для систем с общей памятью Процессор Ядро Ядро Процессор Ядро Ядро Процессор Ядро Ядро Процессор Ядро Ядро Оперативная память (с) Киреев С.E. Процессы и потоки Процесс – это среда выполнения задачи (программы). Процесс создаётся ОС и содержит информацию о программных ресурсах и текущем состоянии выполнения программы. (с) Киреев С.E. Процессы и потоки Поток – это «облегченный процесс». • Создается в рамках процесса, • Имеет свой поток управления, • Разделяет ресурсы процесса-родителя с другими потоками, • Погибает, если погибает родительский процесс. (с) Киреев С.E. Зачем использовать несколько процессов (потоков) в одном приложении • распределение работы между процессорами (ядрами) в мультипроцессорной системе • одновременное выполнение операций вводавывода с использованием центрального процессора для решения других частей задачи • асинхронная обработка событий • выполнение задач в соответствии с приоритетами Преимущества набора потоков вместо набора процессов • Затраты на создание и управление потоками в операционной системе гораздо ниже затрат на процессы • Все потоки в пределах одного процесса разделяют одно адресное пространство. Взаимодействие между потоками реализуется проще, чем между процессами. POSIX Threads API • Управление потоками • Мьютексы • Условные переменные Умножение вектора на вектор (управление потоками и мьютексы) #include <pthread.h> #include <stdio.h> int globalRes = 0; int v1[100], v2[100]; int ids[4] = {0,1,2,3}; pthread_t thrs[4]; pthread_mutex_t mutex; void* prod(void* me) { int offset = *((int*)me); offset *= 25; int res = 0; for(int i = offset; i<offset+25; i++) res += v1[i]*v2[i]; pthread_mutex_lock(&mutex); globalRes += res; pthread_mutex_unlock(&mutex); } int main() { //...инициализация массивов thread_attr_t attrs; if(0!=pthread_attr_init(&attrs, NULL)) { abort() }; pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_JOINABLE); pthread_mutex_init(&mutex, NULL); for(int i = 0; i<4; i++) pthread_create(&thrs[i], &attrs, prod, &ids[i]); pthread_attr_destroy(&attrs); for(int i = 0; i<4; i++) pthread_join(thrs[i], NULL); return 0; } Ошибочная передача параметров int t; pthread_t thrs[NUM_THREADS]; for(t=0; t<NUM_THREADS; t++) { ... pthread_create(&threads[t], NULL, threadFunc, (void *) &t); ... } Основные виды ошибок синхронизации: • Race Condition – состояние гонок – Неупорядоченное чтение-запись или запись-запись общей переменной несколькими потоками – результат недетерминирован • Deadlock – взаимная блокировка – Все потоки ожидают наступления событий, которые никогда не наступят Завершение потока • • • • Возврат из функции потока Вызов функции pthread_exit() из потока Вызов pthread_cancel() другим потоком Завершение всего процесса через exec(), exit(), выход из main() через return. Условные переменные ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ pthread_mutex_t mutex; pthread_cond_t cond; int counter = 0; ПОТОК НОМЕР 1 pthread_mutex_lock(&mutex); if(counter!=criticalValue) pthread_cond_wait(&cond, &mutex); processCriticalValue(); pthread_mutex_unlock(); ПОТОК НОМЕР 2 do { ... pthread_mutex_lock(&mutex); doSomethingWith(&counter); if(counter==criticalValue) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); ... }while(...); Понятие thread-safeness («потокобезопасность») Код называется потокобезопасным, если использование его несколькими потоками без взаимного исключения корректно. В разработке многопоточных приложений важно быть уверенным в том, что используются потокобезопасные библиотеки. Компиляция программ, использующих POSIX Threads API gcc filename.c -lpthread Размер стека: обратить внимание Размер стека потока по умолчанию зависит от реализации POSIX Threads API и должен быть настроен по потребностям приложения с помощью функций: pthread_attr_getstacksize (attr, stacksize) pthread_attr_setstacksize (attr, stacksize) pthread_attr_getstackaddr (attr, stackaddr) pthread_attr_setstackaddr (attr, stackaddr) Источники дополнительных сведений • POSIX Threads Programming tutorial https://computing.llnl.gov/tutorials/pthreads • International Organization for Standardization, Geneva. Information technology --- Portable Operating System Interface (POSIX) --- Part 1: System Application Program Interface (API) [C Language], December 1996. • The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition. Follow the links. http://www.opengroup.org/onlinepubs/009695399/mindex.html • Потоки в UNIX. http://www.opengroup.org/onlinepubs/007908799/xsh/threads.html • Лабораторная работа http://ssdonline.sscc.ru/korneev/Lab9/pthreads1.html • Manual pages. В командной строке UNIX набрать: man <имя фунции>. Вопросы?