Чтение онлайн

на главную - закладки

Жанры

Параллельное и распределенное программирование на С++
Шрифт:

Если неизвестно, какие функции из библиотеки являются безопасными, а какие -нет, программист может воспользоваться одним из следующих вариантов действий.

• Ограничить использование всех опасных функций одним потоком.

• Не использовать безопасные функции вообще.

• Собрать все потенциально опасные функции в один набор механизмов синхронизации.

Еще один вариант — создать интерфейсные классы для всех опасных функций, которые должны использоваться в многопоточном приложении, т.е. опасные функции инкапсулируются в одном интерфейсном классе. Такой интерфейсный класс может быть скомбинирован с соответствующими объектами синхронизации с помощью наследования или композиции и использован

специализированным классом. Такой подход устраняет возможность возникновения условий «гонок».

Разбиение программы на несколько потоков

Выше в этой главе мы рассматривали делегирование работы в соответствии с конкретной стратегией или потоковой моделью. Итак, используются следующие распространенные модели:

• делегирование («управляющий-рабочий»");

• сеть с равноправными узлами;

• конвейер;

• «изготовитель-потребитель».

Каждая модель характеризуется собственной декомпозицией работ (Work Breakdown Structure — WBS), которая определяет, кто отвечает за создание потоков и при каких условиях они создаются. В этом разделе мы рассмотрим пример программы для каж дой модели, использующей функции библиотеки Pthread.

Использование модели делегирования

Мы рассмотрели два подхода к реализации модели делегирования при разделении мы на потоки. Вспомним: в модели делегирования один поток (управляющий) создает другие потоки (рабочие) и назначает каждому из них задачу. Управляющий поток делегирует каждому рабочему потоку задачу, которую он должен выполнить, путем задания некоторой функции. При одном подходе управляющий поток создает рабочие потоки как результат запросов, обращенных к системе. Управляющий поток обрабатывает запрос каждого типа в цикле событий. Как только событие произойдет, будет создан рабочий поток и ему будет назначена задача. Функционирование цикла событий в управляющем потоке и создание рабочих потоков продемонстрировано в листинге 4 .5.

// Листинг 4.5. Подход 1: скелет программы реализации II модели управляющего и рабочих потоков

//...

pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER

int AvailableThreads

pthread_t Thread[Max_Threads]

void decrementThreadAvailability(void)

void incrementThreadAvailability(void)

int threadAvailability(void);

// boss thread

{

//...

if(sysconf(_SC_THREAD_THREADS_MAX) > 0){

AvailableThreads = sysconf(_SC_THREAD_THREADS_MAX)

}

else{

AvailableThreads = Default

}

int Count = 1;

loop while(Request Queue is not empty)

if(threadAvailability){

Count++

decrementThreadAvailability

classify request

switch(request type)

{

case X : pthread_create(&(Thread[Count])...taskX...)

case Y : pthread_create(&(Thread[Count])...taskY...)

case Z : pthread_create(&(Thread[Count])...taskZ...)

//...

}

}

else{

//free up thread resources

}

end loop

}

void *taskX(void *X)

{

// process X type request

incrementThreadAvailability

return(NULL)

}

void *taskY(void *Y)

{

// process Y type request

incrementThreadAvailability

return(NULL)

}

void *taskZ(void *Z)

{

// process Z type request

decrementThreadAvailability

return(NULL)

}

В

листинге 4.5 управляющий поток динамически создает поток для обработки каждого нового запроса, который поступает в систему. Однако существует ограничение на количество потоков (максимальное число потоков), которое можно создать в процессе. Для обработки n типов запросов существует n задач. Чтобы гарантировать, что максимальное число потоков на процесс не будет превышено, определяются следующие дополнительные функции:

threadAvailability

incrementThreadAvailability

decrementThreadAvailability

В листинге 4.6 содержится псевдокод реализации этих функций.

// Листинг 4.6. Функции, которые управляют возможностью

// создания потоков

void incrementThreadAvailability(void)

{

//...

pthread_mutex_lock(&Mutex)

AvailableThreads++

pthread_mutex_unlock(&Mutex)

}

void decrementThreadAvailability(void)

{

//...

pthread_mutex_lock(&Mutex)

AvailableThreads—

pthread_mutex_unlock(&Mutex)

}

int threadAvailability(void)

{

//...

pthread_mutex_lock(&Mutex)

if(AvailableThreads > 1)

return 1

else

return 0

pthread_mutex_unlock(&Mutex)

}

Ф ункция threadAvailability возвратит число 1, если максимально допустимое количество потоков для процесса еще не достигнуто. Эта функция опрашивает глобальную переменную ThreadAvailability, в которой хранится число потоков, еще доступных для процесса. Управляющий поток вызывает функцию decrementThreadAvailability, которая декрементирует эту глобальную переменную до создания им рабочего потока. Каждый рабочий поток вызывает функцию incrementThreadAvailability, которая инкрементирует глобальную переменную ThreadAvailability до начала его выполнения. Обе функции содержат обращение к функции pthread_mutex_lock до получения доступа к этой глобальной переменной и обращение к функции pthread_mutex_unlock после него. Если максимально допустимое количество потоков превышено, управляющий поток может отменить создание потока, если это возможно, или породить другой процесс, если это необходимо. Функции taskX, taskY и taskZ выполняют код, предназначенный для обработки запроса соответствующего типа.

Другой подход к реализации модели делегирования состоит в создании управляющим потоком пула потоков, которым (вместо создания под каждый новый запрос нового потока) переназначаются новые запросы. Управляющий поток во время инициализации создает некоторое количество потоков, а затем каждый созданный поток приостанавливается до тех пор, пока в очередь не будет добавлен новый запрос. Управляющий поток для выделения запросов из очереди по-прежнему использует цикл событий. Но вместо создания нового потока для обслуживания очередного запроса, управляющий поток уведомляет уже существующий поток о необходимости обработки запроса. Этот подход к реализации модели делегирования представлен в листинге 4.7.

Поделиться:
Популярные книги

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

На границе империй. Том 9. Часть 4

INDIGO
17. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 4

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Совершенно несекретно

Иванов Дмитрий
15. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Совершенно несекретно

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Прометей: каменный век II

Рави Ивар
2. Прометей
Фантастика:
альтернативная история
7.40
рейтинг книги
Прометей: каменный век II

Единственная для темного эльфа 3

Мазарин Ан
3. Мир Верея. Драконья невеста
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Единственная для темного эльфа 3

Жандарм

Семин Никита
1. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
4.11
рейтинг книги
Жандарм

Долгий путь домой

Русич Антон
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
6.20
рейтинг книги
Долгий путь домой

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита