Chefeat.ru

Здоровое питание

POSIX Threads

12-10-2023

POSIX Threads — стандарт POSIX реализации потоков (нитей) выполнения, определяющий API для создания и управления ими.

Библиотеки, реализующие этот стандарт (и функции этого стандарта), обычно называются Pthreads (функции имеют приставку «pthread_»). Хотя наиболее известны варианты для Unix-подобных операционных систем, таких как Linux или Solaris, но существует и реализация для Microsoft Windows (Pthreads-w32)

Содержание

Основные функции стандарта

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

  • Типы данных:
    • pthread_t: дескриптор потока
    • pthread_attr_t: перечень атрибутов потока
  • Функции управления потоками:
    • pthread_create(): создание потока
    • pthread_exit(): завершение потока (должна вызываться функцией потока при завершении)
    • pthread_cancel(): отмена потока
    • pthread_join(): заблокировать выполнение потока до прекращения другого потока, указанного в вызове функции
    • pthread_detach(): освободить ресурсы занимаемые потоком (если поток выполняется, то освобождение ресурсов произойдёт после его завершения)
    • pthread_attr_init(): инициализировать структуру атрибутов потока
    • pthread_attr_setdetachstate(): указать системе, что после завершения потока она может автоматически освободить ресурсы, занимаемые потоком
    • 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 <pthread.h>
 
class Thread
{
private:
    pthread_t thread;
 
    Thread(const Thread& copy);         // copy constructor denied
    static void *thread_func(void *d)   { ((Thread *)d)->run(); }
 
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'. Основной поток ждёт завершения обоих дочерних потоков.

См. также

Ссылки

  • Спецкурс "Многонитевое программирование" ВМиК МГУ  (рус.)
  • Многопоточное программирование (Учебник Pthreads)  (англ.)
  • Примеры использования Pthreads  (англ.)
  • Примеры использования Pthreads в C/C++  (англ.)
  • Статья «Объясняя потоки POSIX», Даниэля Роббинса (основателя проекта Gentoo)  (англ.)
  • Интервью «10 вопросов Девиду Бутенхофу о параллельном программировании и потоках POSIX» с Майклом Суиссом  (англ.)
  • The Open Group Base Specifications Issue 6, IEEE Std 1003.1  (англ.)
  • Pthread Win-32, Basic Programming (англ.)
  • Pthreads Tutorial (англ.)
  • C/C++ Tutorial: using Pthreads (англ.)
  • Article «POSIX threads explained» by Daniel Robbins (Gentoo Linux founder) (англ.)
  • Interview «Ten Questions with David Butenhof about Parallel Programming and POSIX Threads» by Michael Suess (англ.)
  • Open Source POSIX Threads for Win32 (англ.)
  • The Open Group Base Specifications Issue 6, IEEE Std 1003.1 (англ.)
  • GNU Portable threads (англ.)
  • Flash Presentation on pThread (англ.)
  • Pthreads Presentation at 2007 OSCON (O’Reilly Open Source Convention) by Adrien Lamothe. An overview of Pthreads with current trends. (англ.)

POSIX Threads.

© 2014–2023 chefeat.ru, Россия, Челябинск, ул. Речная 27, +7 (351) 365-27-13