Камерон Хьюз - Параллельное и распределенное программирование на С++
- Название:Параллельное и распределенное программирование на С++
- Автор:
- Жанр:
- Издательство:Издательский дом «Вильямс»
- Год:2004
- Город:МоскваСанкт-ПетербургКиев
- ISBN:ISBN 5-8459-0686-5 (рус.)ISBN 0-13-101376-9 (англ.)
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Камерон Хьюз - Параллельное и распределенное программирование на С++ краткое содержание
Эта книга адресована программистам, проектировщикам и разработчикам программных продуктов, а также научным работникам, преподавателям и студентам, которых интересует введение в параллельное и распределенное программирование с использованием языка С++.
Параллельное и распределенное программирование на С++ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
pthread_rwlock_init(&RWLock,NULL); // Устанавливаем атрибуты мьютекса. pthread_create(&ThreadA, NULL, producerl, NULL) pthread_create(&ThreadB, NULL, consumerl, NULL) pthread_create(&ThreadC,NULL,producer2,NULL) pthread_create(&ThreadD,NULL, consumer2,NULL) //.. .
return(0);
}
В листинге 5.3 создаются четыре потока. Два потока, ThreadA и ThreadC, выполняют роль изготовителей, а остальные два (ThreadB и ThreadD) — потребителей. Все потоки имеют критический раздел, который защищается объектом блокировки чтения-записи RWLock. Потоки ThreadB и ThreadD могут входить в свои критические разделы параллельно или последовательно, но это исключено, если поток ThreadA или ThreadC пребывает в своем критическом разделе. Потоки ThreadA и ThreadC не могут входить в свои критические разделы параллельно. Частичная таблица решении для листинга 5.3 показана в табл. 5.6.
Таблица 5.6. Час т ич н ая таблица решений для листинга 5.3
Поток А | Поток В | Поток С | Поток D |
(выполняет запись) | (выполняет чтение) | (выполняет запись) | (выполняет чтение) |
Нет | Нет | Нет | Да |
Нет | Нет | Да | Нет |
Нет | Да | Нет | Нет |
Нет | Да | Нет | Да |
Да | Нет | Нет | Нет |
Условные переменные
Условная переменная представляет собой семафор, используемый для сигнализации о событии, которое произошло. Сигнала о том, что произошло некоторое событие, может ожидать один или несколько процессов (или потоков) от других процессов или потоков. Следует понимать различие между условными переменными и рассмотренными выше мьютексными семафорами. Назначение мьютексного семафора и блокировок чтения-записи — синхронизировать доступ к данным, в то время как условные переменные обычно используются для синхронизации последовательности операций. По этому поводу в своей книге UNIX Network Programming прекрасно высказался Ричард Стивенс (W. Richard Stevens): « Мьютексы нужно использовать для блокирования, а не для ожидания ».
В листинге 4.6 поток-«потребитель» содержал цикл:
15 while(TextFiles.empty())
16 {}
Поток-«потребитель» выполнял итерации цикла до тех пор, пока в очереди TextFilesбыли элементы. Этот цикл можно заменить условной пере м енной. Поток-«изготовитель» сигналом уведомляет потребителя о том, что в очередь помещены элементы. Поток-«потребитель» может ожидать до тех пор, пока не получит сигнал, а затем перейдет к обработке очереди.
Условная переменная имеет тип pthread_cond_t. Ниже перечислены типы операций, которые может она выполнять:
• инициализация;
• разрушение;
• ожидание;
• ожидание с ограничением по времени;
• адресная сигнализация;
• всеобщая сигнализация;
Операции инициализации и разрушения выполняются условными переменными подобно аналогичным операциям других мьютексов. Функции класса pthread_cond_t,которые реализуют эти операции, перечислены в табл. 5.7.
Ожидание | int pthread_cond_wait(pthread_cond_t * restrict cond, pthread_mutex_t *restrict mutex); | int pthread_cond_timedwait( pthread_cond_t * restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); |
Сигнализация | int pthread_cond_signal(pthread_cond_t*cond); | int pthread_cond_broadcast( pthread_cond_t *cond); |
Разрушение | int pthread_cond_destroy(pthread_cond_t*cond); | |
Инициализация | int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); | |
pthread_cond_t cond =PTHREAD_C OND_INITIALIZER; |
Таблица 5.7. Функции класса pthread_cond_t, которые реализуют операции условных переменных
Условные переменные используются совместно с мьютексами. При попытке заблокировать мьютекс поток или процесс будет заблокирован до тех пор, пока мьютекс не освободится. После разблокирования поток или процесс получит мьютекс и продолжит свою работу. При использовании условной переменной ее необходимо связать с мьютексом.
//. . .
pthread_mutex_lock(&Mutex) ;
pthread_cond_wait(&EventMutex, &Mutex);
//. . .
pthread_mutex_unlock(&Mutex) ;
Итак, некоторая задача делает попытку заблокировать мьютекс. Если мьютекс уже заблокирован, то эта задача блокируется. После разблокирования задача освободит мьютекс Mutex и при этом будет ожидать сигнала для условной переменной EventMutex .Если мьютекс не заблокирован, задача будет ожидать сигнала неограниченно долго. При ожидании с ограничением по времени задача будет ожидать сигнала в течение заданного интервала времени. Если это время истечет до получения задачей сигнала, функция возвратит код ошибки. Затем задача вновь затребует мьютекс.
Выполняя адресную сигнализацию, задача уведомляет другой поток или процесс о том, что произошло некоторое событие. Если задача ожидает сигнала для заданной условной переменной, эта задача будет разблокирована и получит мьютекс. Если сразу несколько задач ожидают сигнала для заданной условной переменной, то разблокирована будет только одна из них. Остальные задачи будут ожидать в очереди, и их разблокирование будет происходить в соответствии с используемой стратегией планирования. При выполнении операции всеобщей сигнализации уведомление получат все задачи, ожидающие сигнала для заданной условной переменной. При разблокировании нескольких задач они будут состязаться за право владения мьютексом в соответствии с используемой стратегией планирования. В отличие от операции ожидания, задача, выполняющая операцию сигнализации, не предъявляет прав на владение мьютексом, хотя это и следовало бы сделать.
Условная переменная также имеет атрибутный объект, функции которого перечислены в табл. 5.8.
Таблица 5.8. Функции доступа к атрибутному объекту для условной переменной типа pthread_cond_t
• int pthread_condattr_init( pthread_condattr_t * attr) Инициализирует атрибутный объект условной переменной, заданный параметром attr, значениями, действующими по умолчанию для всех атрибутов, определенных реализацией;
• int pthread_condattr_destroy( pthread_condattr_t * attr) ; Разрушает атрибутный объект условной переменной, заданный параметром attr. Этот объект можно инициализировать повторно, вы-звав функцию pthread_condattr_init ()
• int pthread_condattr_setpshared( pthread_condattr_t * attr,int pshared);
• int pthread_condattr_getpshared( const pthread_condattr_t * restrict attr, int *restrict pshared); Устанавливает или возвращает атрибут process-shared атрибутного объекта условной переменной, заданного параметром attr. Параметр pshared может содержать следующие значения:
• PTHREAD_PROCESS_SHARED(разрешает блокировку чтения-записи, разделяемую любыми потоками, которые имеют доступ к памяти, выделенной для этой условной переменной, даже если потоки принадлежат различным процессам);
• PTHREAD_PROCESS_PRIVATE(Условная Переменная разделяется между потоками одного процесса)
• int pthread_condattr_setclock( pthread_condattr_t * attr, clockid_t clock_id);
Читать дальшеИнтервал:
Закладка: