UML диаграммы, используемые при описании параллельных задач:

Название Описание
Диаграмма (видов) деятельности Разновидность Диаграммы состояний, в которой большинство состояний - это виды деятельности, а большинство переходов активизируются при выполнении некоторого действия в исходных состояниях
Диаграмма взаимодействия Отображает взаимодействие между объектами. Взаимодействия описываются сообщениями, которыми они обмениваются. Выделяют диаграммы сотрудничества, диаграммы последовательностей и диаграммы (видов) деятельности
Диаграммв (параллельных) состояний Диаграмма показывает последовательность преобразований объекта в процессе его реакции на события. Особенность в том, что эти преобразования могут происходить одновременно
Диаграмма последовательностей Диаграмма взаимодействия, в которой отражается организация структуры объектов, принимающих или отправляющих сообщения (акцент на упорядочение во времени)
Диаграмма сотрудничества Диаграмма взаимодействия, в которой отображается организация структуры объектов, принимающих и отправляющих сообщения (акцент на структурной организации)
Диаграмма развёрт-ия (внедрения) Динамическая конфигурация узлов обработки, аппаратных средств и программных компонентов в системе
Диаграмма компонентов Диаграмма взаимодействия, в которой отображается организация физических модулей программного кода (пакетов) в системе и зависимости между ними

Процессы

Выделяют системные и пользовательские. Пользовательские могут обращаться к системным для выполнения каких-либо действий, говорят, что он пребывает в привилегированном режиме (kernrel mode). При этом он не может быть выгружен другим пользовательским процессом.

Диаграмма состояний процесса:

Диаграмма состояний процесса

Функции дробления процессов:

  • fork + execl

    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc, char * argv[])
    {
        pid_t result = fork();
        if(result == 0)
        {
                execlp("dig", "@server4ibm", "+short", "hoxnox1.otdel4.a", NULL);
                exit(EXIT_SUCCESS);
        }
        else
        {
                execlp("dig", "@server4ibm", "+short", "poma-k-n.otdel4.a", NULL);
                exit(EXIT_SUCCESS);
        }
        return 0;
    }
    
  • system Аналогична запуску fork + exec, но родительский процесс засыпает на время запуска оболчки с сыновним процессом. То есть родительский и сыновний процессы синхронны.

    #include <stdlib.h>
    
    int main(int argc, char * argv[])
    {
        system("dig @server4ibm +short hoxnox1.otdel4.a");
        system("dig @server4ibm +short poma-k-n.otdel4.a");
        return 0;
    }
    
  • posix_spawn В отличии от первых, позволяет * Игнорировать сыновним процессом сигналов, игнорируемых родительским. Или, напротив, устанавливать для действий по умолчанию * обмениваться дескрипторами файлов * установить для сыновнего процесса идентификатор группы * установить стратегию планирования сыновнего процесса отличной от стратегии родителя

    #include <spawn.h>
    #include <stdio.h>
    
    int main(int argc, char * argv[])
    {
        posix_spawnattr_t attr;
        posix_spawn_file_actions_t file_actions;
        pid_t pid;
        char* const args[] = {"dig", "@server4ibm", "+short", "hoxnox1.otdel4.a", NULL};
        char* const args2[] = {"dig", "@server4ibm", "+short", "hoxnox1.otdel4.a", NULL};
        char* const envs[] = {"PROCESSES=2", NULL};
        int stat;
        posix_spawnattr_init(&attr);
        posix_spawn_file_actions_init(&file_actions);
        posix_spawnp(&pid, "dig", &file_actions, &attr, args, envs);
        posix_spawnp(&pid, "dig", &file_actions, &attr, args2, envs);
        wait(&stat);
        wait(&stat);
        return 0;
    }
    

Для того, чтобы заставить родительские процессы ждать в асинхронных вариантах, можно использовать фнкции wait и waitpid.

Ресурсы

Разделение ресурсов процессами можно изображать соответствующим графом. Точки внутри ресурсов обозначают количество ресурсов данного типа (например процессоры в многопроцессорной системе).

Граф разделения ресурсов процессами

Функции по работе с ресурсами:

  • Лимитирование

    struct rlimit
    {
        rlim_t rlim_cur;
        rlim_t rlim_max;
    }
    
    • int setrlimit(int resource, const struct rlimit *rlp)
    • int getrlimit(int resource, struct rlimit *rlp)
  • Использование

    • int getrusage(int who, struct rusage *r_usage)

Способы реализации параллелизма

Способы реализации параллелизма

Потоки

Потоки во многом похожи на процессы. Главное отличие состоит в том, что каждый процесс имеет собственное адресное пространство. Если процесс создает множество потоков, то все они будут работать в одном адресном пространстве.

Потоки, в отличии от процессов равноправны и каждый поток может влиять на другие. В процессах же только родительский может влиять на сыновние.

Атрибуты потоков:

Атрибуты потоков

Модели функционирования потоков

Модели функционирования потоков

Pthread

#include <pthread.h>
#include <stdio.h>

void *dig1(void *arg)
{
    int n = *(int *)arg;
    printf("thread A: %d * %d = %d\n", n, n, n*n);
    return 0;
}

void *dig2(void *arg)
{
    int n = *(int *)arg;
    printf("thread B: %d + %d = %d\n", n, n, n+n);
    return 0;
}

int main()
{
    int N = 5;
    pthread_t threadA, threadB;
    pthread_create(&threadA, NULL, dig1, &N);
    pthread_create(&threadB, NULL, dig2, &N);
    pthread_join(threadA, NULL);
    pthread_join(threadB, NULL);
    return 0;
}

Атрибуты потока

  • размер стека потока
  • местоположение стека потока
  • стратегия планирования, наследование и параметры
  • тип потока: открепленный или присоединяемый
  • область конструкции потока

Закрытие потока

Один поток может попытаться отменить другой вызовом pthread_cancel, но аннулируемый сам определяет когда ему это лучше сделать и делать ли вообще см. pthread_setcanceltype pthread_setcancelstate. Кроме того, существует определённый механизм отмены - должны быть вызваны функции заданные pthread_cleanup_push.

Соревнование потоков

На то в каком порядке потока будут выделяться ресурсы влияют 3 вещиЖ

  • область конкуренции (pthread_attr_setscope)
    • уровень системы
    • уровень процесса
  • стратегия планирования (pthread_attr_setinheritsched, pthread_attr_setshedpolicy)
    • FIFO
    • RR
    • other
  • Приоритет (pthread_attr_setshedparam)

Синхронизация

Типы синхронизации

  • СС
  • СФ
  • ФС
  • ФФ

Стратегии управления памятью

  • exclusive read & exclusive write EREW
  • concurrent read & exclusive write CREW
  • exclusive read & concurrent write ERCW
  • concurrent read & concurrent write CRCW

Семафоры

Мьютексный семафор

Функции pthread для работы с мьютексами имеют префикс pthread_mutex.

Мьютекс позволяет процессу или потоку при входе в критический участок заблокировать какой-либо объект (см. lock, timedlock, unlock, trylock, destroy).

Перед использованием мьютекс должен быть проинициализирован или значениями по умолчанию:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

или с помощью соответствующей структуры pthread_mutexattr_t.

Атрибуты

  • закрытый/разделяемый (разделяемый может использоваться несколькими процессами) (pshared)
  • блокированный/деблокированный
  • предельный приоритет (proiceiling)
  • протокол (protocol)
  • тип (type)

Пример использования разделяемого мьютекса:

int result;
pthread_mutex_t mutex1;
pthread_mutexattr_t mutex_attr;

int main()
{
        pthread_mutexattr_init(&mutex_attr);
        pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
        pthread_mutex_init(&mutex1, &mutex_attr);
        if( (result = fork()) == 0 )
        { // сыновний процесс
                pthread_mutex_lock(&mutex1);
                // Критический раздел
                pthread_mutex_unlock(&mutex1);
        }
        else
        { // родительский процесс
                pthread_mutex_lock(&mutex1);
                // Критический раздел
                pthread_mutex_unlock(&mutex1);
        }
        return 0;
}

Блокировки на чтение и запись

Более интеллектуальный тип блокировки вместо одно операции блокирования имеется две:

  • pthread_rwlock_rdlock()
  • pthread_rwlock_wrlock()

Данные блокировки реализуют CREW стратегию управления. Один нюанс - при монопольной записи, запрещено какое-либо чтение.

Условная переменная

pthread_cond_t позволяет реализовать

  • ожидание (pthread_cond_wait)
  • ожидание с ограничением по времени (pthread_cond_timedwait)
  • адресная сигнализация (pthread_cond_signal)
  • всеобщая сигнализация (pthread_cond_broadcast)

Используют для управления отношениями синхронизацииша