В вычислительной технике потоки POSIX , обычно называемые pthreads , представляют собой модель выполнения , которая существует независимо от языка программирования , а также модель параллельного выполнения . Она позволяет программе управлять несколькими различными потоками работы, которые перекрываются во времени. Каждый поток работы называется потоком , а создание и управление этими потоками достигается путем выполнения вызовов API потоков POSIX . Потоки POSIX представляют собой API, определенный стандартом Института инженеров по электротехнике и электронике (IEEE) POSIX .1c, расширения потоков (IEEE Std 1003.1c-1995) .
Реализации API доступны во многих Unix-подобных POSIX-совместимых операционных системах , таких как FreeBSD , NetBSD , OpenBSD , Linux , macOS , Android [1] , Solaris , Redox и AUTOSAR Adaptive , обычно в составе библиотеки libpthread . Существуют также реализации для DR-DOS и Microsoft Windows : в подсистеме SFU/SUA , которая обеспечивает собственную реализацию ряда POSIX API, а также в сторонних пакетах, таких как pthreads-w32 , [2] который реализует pthreads поверх существующего Windows API .
pthreads определяет набор типов , функций и констант языка программирования C. Он реализован с помощью заголовка и библиотеки потоков .pthread.h
Существует около 100 процедур потоков, все они имеют префиксы pthread_
и их можно разделить на пять групп:
API семафора POSIX работает с потоками POSIX, но не является частью стандарта потоков, поскольку определен в стандарте POSIX.1b, Real-time extensions (IEEE Std 1003.1b-1993) . Следовательно, процедуры семафора имеют префикс sem_
вместо pthread_
.
Пример, иллюстрирующий использование pthreads в C:
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <pthread.h> #include <unistd.h> #define NUM_THREADS 5void * perform_work ( void * arguments ) { int index = * ( ( int * ) arguments ); int sleep_time = 1 + rand () % NUM_THREADS ; printf ( "Поток %d: запущен. \n " , index ); printf ( "Поток %d: будет находиться в спящем режиме в течение %d секунд. \n " , index , sleep_time ); sleep ( sleep_time ); printf ( "Поток %d: завершен. \n " , index ); return NULL ; } int main ( void ) { pthread_t threads [ NUM_THREADS ]; int thread_args [ NUM_THREADS ]; int i ; int result_code ; //создаем все потоки один за другим for ( i = 0 ; i < NUM_THREADS ; i ++ ) { printf ( "In main: Создание потока %d. \n " , i ); thread_args [ i ] = i ; result_code = pthread_create ( & threads [ i ], NULL , perform_work , & thread_args [ i ]); assert ( ! result_code ); } printf ( "В главном: Все потоки созданы. \n " ); //ждем завершения каждого потока for ( i = 0 ; i < NUM_THREADS ; i ++ ) { result_code = pthread_join ( threads [ i ], NULL ); assert ( ! result_code ); printf ( "In main: Поток %d завершен. \n " , i ); } printf ( "Основная программа завершена. \n " ); return 0 ; }
Эта программа создает пять потоков, каждый из которых выполняет функцию perform_work , которая выводит уникальный номер этого потока на стандартный вывод. Если программист хочет, чтобы потоки взаимодействовали друг с другом, это потребует определения переменной вне области действия любой из функций, сделав ее глобальной переменной . Эту программу можно скомпилировать с помощью компилятора gcc с помощью следующей команды:
gcc pthreads_demo.c -pthread -o pthreads_demo
Вот один из возможных результатов работы этой программы.
In main: Создание потока 0. In main: Создание потока 1. In main: Создание потока 2. In main: Создание потока 3. Поток 0: Запущен. In main: Создание потока 4. Поток 3: Запущен. Поток 2: Запущен. Поток 0: Будет спать 3 секунды. Поток 1: Запущен. Поток 1: Будет спать 5 секунд. Поток 2: Будет спать 4 секунды. Поток 4: Запущен. Поток 4: Будет спать 1 секунду. In main: Все потоки созданы. Поток 3: Будет спать 4 секунды. Поток 4: Завершен. Поток 0: Завершен. In main: Поток 0 завершен. Поток 2: Завершен. Поток 3: Завершен. Поток 1: Завершен. In main: Поток 1 завершен. In main : Поток 2 завершен. In main: Поток 3 завершен. In main: Поток 4 завершен. Основная программа завершена.
Windows изначально не поддерживает стандарт pthreads, поэтому проект Pthreads4w стремится предоставить переносимую и открытую реализацию оболочки . Его также можно использовать для переноса программного обеспечения Unix (использующего pthreads) с небольшими или нулевыми изменениями на платформу Windows. [4] Pthreads4w версии 3.0.0 [5] или более поздней, выпущенной под лицензией Apache Public License v2.0, совместима с 64-битными или 32-битными системами Windows. Версия 2.11.0 [6], выпущенная под лицензией LGPLv3, также совместима с 64-битными или 32-битными системами.
Проект Mingw-w64 также содержит реализацию оболочки 'pthreads, winpthreads , которая пытается использовать больше собственных системных вызовов, чем проект Pthreads4w. [7]
Подсистема среды Interix, доступная в пакете служб Windows для UNIX/подсистемы для приложений на базе UNIX, предоставляет собственный порт API pthreads, т. е. не сопоставленный с API Win32, а построенный непосредственно на интерфейсе системных вызовов операционной системы . [8]