POSIX Threads

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

POSIX Threads — стандарт POSIX реализации потоков (нитей) выполнения. Стандарт POSIX.1c, Threads extensions (IEEE Std 1003.1c-1995) определяет API для управления потоками, их синхронизации и планирования.

Реализации данного API существуют для большого числа UNIX-подобных ОС (GNU/Linux, Solaris, FreeBSD, OpenBSD, NetBSD), а также для Mac OS X и Microsoft Windows и других ОС.

Библиотеки, реализующие этот стандарт (и функции этого стандарта), обычно называются Pthreads (функции имеют приставку «pthread_»).

Основные функции стандарта[править | править вики-текст]

Pthreads определяет набор типов и функций на языке программирования Си. Заголовочный файл — pthread.h.

  • Типы данных:
    • pthread_t: дескриптор потока;
    • pthread_attr_t: перечень атрибутов потока;
    • pthread_barrier_t: барьер;
    • pthread_barrierattr_t: атрибуты барьера;
    • pthread_cond_t: условная переменная;
    • pthread_condattr_t: атрибуты условной переменной;
    • pthread_key_t: данные, специфичные для потока;
    • pthread_mutex_t: мьютекс;
    • pthread_mutexattr_t: атрибуты мьютекса;
    • pthread_rwlock_t: ;
    • pthread_rwlockattr_t: ;
    • pthread_spinlock_t: спинлок;
  • Функции управления потоками:
    • pthread_create(): создание потока.
    • pthread_exit(): завершение потока (должна вызываться функцией потока при завершении).
    • pthread_cancel(): отмена потока.
    • pthread_join(): подключиться к другому потоку и ожидать его завершения; поток, к которому необходимо подключиться, должен быть создан с возможностью подключения (PTHREAD_CREATE_JOINABLE).
    • pthread_detach(): отключиться от потока, сделав его при этом отдельным (PTHREAD_CREATE_DETACHED).
    • pthread_attr_init(): инициализировать структуру атрибутов потока.
    • pthread_attr_setdetachstate(): указывает параметр "отделимости" потока (detach state), который говорит о возможности подключения к нему (при помощи pthread_join) других потоков (значение PTHREAD_CREATE_JOINABLE) для ожидания окончания или о запрете подключения (значение PTHREAD_CREATE_DETACHED); ресурсы отдельного потока (PTHREAD_CREATE_DETACHED) при завершении автоматически освобождаются и возвращаются системе.
    • pthread_attr_destroy(): освободить память от структуры атрибутов потока (уничтожить дескриптор).
  • Функции синхронизации потоков:
    • pthread_mutex_init(), pthread_mutex_destroy(), pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock(): с помощью мьютексов.
    • pthread_cond_init(), pthread_cond_signal(), pthread_cond_wait(): с помощью условных переменных.

Пример[править | править вики-текст]

Пример использования потоков на языке C:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
 
static void wait_thread(void)
{
    time_t start_time = time(NULL);
 
    while (time(NULL) == start_time)
    {
        /* do nothing except chew CPU slices for up to one second. */
    }
}
 
static void *thread_func(void *vptr_args)
{
    int i;
 
    for (i = 0; i < 20; i++)
    {
        fputs("  b\n", stderr);
        wait_thread();
    }
 
    return NULL;
}
 
int main(void)
{
    int i;
    pthread_t thread;
 
    if (pthread_create(&thread, NULL, thread_func, NULL) != 0)
    {
        return EXIT_FAILURE;
    }
 
    for (i = 0; i < 20; i++)
    {
        puts("a");
        wait_thread();
    }
 
    if (pthread_join(thread, NULL) != 0)
    {
        return EXIT_FAILURE;
    }
 
    return EXIT_SUCCESS;
}

Пример использования потоков на языке C++:

#include <cstdlib>
#include <iostream>
#include <memory>
#include <unistd.h>
#include <pthread.h>
 
class Thread
{
private:
    pthread_t thread;
 
    Thread(const Thread& copy);         // copy constructor denied
    static void *thread_func(void *d)   { ((Thread *)d)->run(); return NULL; }
 
public:
    Thread()             {}
    virtual ~Thread()    {}
 
    virtual void run() = 0;
 
    int start()          { return pthread_create(&thread, NULL,
                           Thread::thread_func, (void*)this); }
    int wait ()          { return pthread_join  (thread, NULL); }
};
 
typedef std::auto_ptr<Thread> ThreadPtr;
 
int main(void)
{
    class Thread_a:public Thread
    {
    public:
        void run()
        {
            for (int i=0; i<20; i++, sleep(1))
                std::cout << "a  " << std::endl;
        }
    };
 
    class Thread_b:public Thread
    {
    public:
	void run()
        {
            for(int i=0; i<20; i++, sleep(1))
                std::cout << "  b" << std::endl;
        }
    };
 
    ThreadPtr a( new Thread_a() );
    ThreadPtr b( new Thread_b() );
 
    if (a->start() != 0 || b->start() != 0)
        return EXIT_FAILURE;
 
    if (a->wait() != 0 || b->wait() != 0)
        return EXIT_FAILURE;
 
    return EXIT_SUCCESS;
}

Представленные программы используют два потока, печатающих в консоль сообщения, один, печатающий 'a', второй — 'b'. Вывод сообщений смешивается в результате переключения выполнения между потоками или одновременном выполнении на мультипроцессорных системах.

Отличие состоит в том, что программа на C создает один новый поток для печати 'b', а основной поток печатает 'a'. Основной поток (после печати 'aaaaa….') ждёт завершения дочернего потока.

Программа на C++ создает два новых потока, один печатает 'a', второй, соответственно, — 'b'. Основной поток ждёт завершения обоих дочерних потоков.

См. также[править | править вики-текст]

Ссылки[править | править вики-текст]