Олег Цилюрик - QNX/UNIX: Анатомия параллелизма
- Название:QNX/UNIX: Анатомия параллелизма
- Автор:
- Жанр:
- Издательство:Символ-Плюс
- Год:2006
- Город:Санкт-Петербург
- ISBN:5-93286-088-Х
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Олег Цилюрик - QNX/UNIX: Анатомия параллелизма краткое содержание
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса. Некоторые из результатов испытаний тестовых примеров будут большим сюрпризом даже для самых бывалых программистов. Тем не менее излагаемые техники вполне доступны и начинающим программистам: для изучения материала требуется базовое знание языка программирования C/C++ и некоторое понимание «устройства» современных многозадачных ОС UNIX.
В качестве «испытательной площадки» для тестовых фрагментов выбрана ОСРВ QNX, что позволило с единой точки зрения взглянуть как на специфические механизмы микроядерной архитектуры QNX, так и на универсальные механизмы POSIX. В этом качестве книга может быть интересна и тем, кто не использует (и не планирует никогда использовать) ОС QNX: программистам в Linux, FreeBSD, NetBSD, Solaris и других традиционных ОС UNIX.
QNX/UNIX: Анатомия параллелизма - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Блокировки чтения/записи
Блокировка чтения/записи является специфическим механизмом, отличающимся от рассмотренных выше. Специфика состоит в следующем:
• Данный тип блокировки даже по POSIX является альтернативным. Часто этот тип блокировки может реализовываться как надстройка над уже существующими базовыми примитивами. У. Стивенс [2] показывает один из вариантов такой «оберточной» реализации и приводит ссылки на еще несколько вариантов, в том числе и на предложенный стандартом IEEE 1996.
• Функциональность, обеспечиваемая блокировкой чтения/записи, может быть предоставлена и простым использованием других базовых механизмов, однако реализация с блокировкой чтения/записи может быть намного эффективнее по производительности приложения (как мы увидим позже).
Целесообразность привлечения блокировки чтения/записи возникает тогда, когда все множество потоков может быть отчетливо разделено на две группы: потоки, только считывающие защищаемые блокировкой данные (читатели), и потоки, модифицирующие эти данные (писатели). Такая ситуация традиционно возникает в области работы с объемными, сложно структурированными данными.
При использовании блокировки чтения/записи, в отличие от других ранее рассмотренных механизмов, вводится различие между получением такой блокировки для считывания и записи. При этом действуют следующие правила:
• Любое количество потоков может заблокировать ресурс для считывания, если ни один поток не заблокировал его по записи.
• Наличие множественных блокировок по чтению не препятствует (не блокирует) ни одному из потоков-читателей выполнять свои операции с ресурсом.
• Блокировка по записи может быть установлена, только если ни один поток не блокирует ресурс ни по чтению, ни по записи.
• Блокировка по записи запрещает дальнейшую блокировку ресурса (блокирует запрашивающий процесс) и по чтению, и по записи.
Функции работы с блокировками чтения/записи объявлены, как и большинство примитивов синхронизации, в заголовочном файле .
Операции с блокировками чтения/записи
Инициализация объекта блокировки
int pthread_rwlock_init(pthread_rwlock_t* rwl,
const pthread_rwlockattr_t* attr);
int pthread_rwlock_destroy(pthread_rwlock_t* rwl);
Вызов функций инициализирует/разрушает блокировку чтения/записи. При инициализации блокировки ей передается структура параметров блокировки pthread_rwlockattr_t
, в которой могут устанавливаться параметры доступа к объекту из других процессов.
Вместо прямого вызова функции pthread_rwlock_init()
для начальной инициализации статических блокировок чтения/записи (глобальных на уровне файла кода или пространства имен namespace
либо явно описанных с квалификатором static
) можно воспользоваться макросом PTHREAD_RWLOCK_INITIALIZER
.
Захват блокировки чтения/записи
В связи со спецификой применения блокировок чтения/записи этот объект синхронизации имеет две группы функций захвата, позволяющих по-разному регулировать доступ к защищаемому участку кода.
К первой группе относятся функции, допускающие рекурсивный захват объекта синхронизации и совместное использование участка кода. Это так называемые функции блокировки по чтению .
Вторая группа функций допускает только эксклюзивный захват объекта синхронизации и к выполнению защищаемого кода допускается только один поток. Это функции блокировки по записи .
int pthread_rwlock_rdlock(pthread_rwlock_t* rwl);
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwl);
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock,
const struct timespec* abs);
Эта группа функций позволяет множественный захват объекта синхронизации и одновременное исполнение защищаемого участка кода, с которым ассоциируется переменная rwl
. Данная группа функций предназначена для обеспечения одновременного чтения данных, разделяемых несколькими потоками. Выполнение захвата с использованием этой группы функций будет блокировано, если объект синхронизации, на который указывает rwl
, уже захвачен одной из функций эксклюзивного исполнения кода (блокировки по записи).
Первая функция в группе позволяет выполнить простой захват объекта синхронизации. При рекурсивном захвате с помощью любой из указанных функций необходимо помнить, что освобождение должно производиться столько же раз, сколько и захват.
Функция pthread_rwlock_rdlock()
может возвращать следующие значения:
EOK
— успешное выполнение;
EAGAIN
— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER
) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EDEADLK
— вызывающий поток уже провел эксклюзивный захват (блокировку по записи) объекта синхронизации, на который ссылается rwl
, и повторный захват на чтение привел бы к полному («мертвому») блокированию потока;
EFAULT
— сбой при обращении ядра к rwl
;
EINVAL
— rwl
указывает на неверный объект блокировки чтения/записи.
Вторая из перечисленных функций проверяет, не находится ли соответствующий объект синхронизации в эксклюзивном использовании, и если это так, она возвращает соответствующее значение без последующего ожидания освобождения объекта синхронизации.
Функция pthread_rwlock_tryrdlock()
возвращает следующие значения:
EOK
— успешное выполнение;
EAGAIN
— при первом использовании статически инициированной блокировки чтения/записи ( PTHREAD_RWLOCK_INITIALIZER
) недостаточно системных ресурсов для инициализации блокировки чтения/записи;
EBUSY
— блокировка чтения/записи блокирована по записи (собственно, это и есть основной мотив использования именно этого вызова);
EDEADLK
— вызывающий поток уже провел эксклюзивный захват (блокировку по записи) объекта синхронизации, на который ссылается rwl
;
EFAULT
— сбой при обращении ядра к rwl
;
EINVAL
— rwl
указывает на неверный объект блокировки чтения/записи.
Третья функция из группы предусматривает завершение блокировки ожидания освобождения объекта синхронизации при возникновении блокировки по записи или по истечении заданного тайм-аута ожидания.
Функция pthread_rwlock_timedrdlock()
может возвращать следующие коды ошибки:
EAGAIN
— система не может захватить блокировку по чтению, поскольку достигнуто максимальное число блокировок чтения для данного объекта; [37] Забавно! Речь идет об исчерпании количества рекурсивных захватов для внутреннего мьютекса. Здесь есть некоторое несоответствие с другими объектами синхронизации.
Интервал:
Закладка: