Типичные ошибки связанные с использованием блокировки

Попытка снять блокировку не из того потока, который ее установил

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

Некорректно:

omp_lock_t myLock; omp_init_lock(&myLock); #pragma omp parallel sections { #pragma omp section { ... omp_set_lock(&myLock); ... } #pragma omp section { ... omp_unset_lock(&myLock); ... } }

В Си++ этот код приводит к ошибке во время выполнения программы. Поскольку операции установки и снятия блокировки аналогичны входу в критическую секцию и выходу из нее, каждый из использующих блокировку потоков должен выполнять обе операции. Корректная версия кода будет выглядеть следующим образом:

Корректно:

omp_lock_t myLock; omp_init_lock(&myLock); #pragma omp parallel sections { #pragma omp section { ... omp_set_lock(&myLock); ... omp_unset_lock(&myLock); ... } #pragma omp section { ... omp_set_lock(&myLock); ... omp_unset_lock(&myLock); ... } }

Попытка использования блокировки как барьера

Функция omp_set_lock блокирует выполнение потока до тех пор, пока переменная, использующаяся для блокировки, не станет доступна, то есть до тех пор, пока тот же самый поток не вызовет функцию omp_unset_lock. Следовательно, как уже говорилось в описании предыдущей ошибки, каждый поток должен содержать вызовы обеих функций. Однако, начинающий программист, недостаточно хорошо понимающий принципы работы OpenMP, может попытаться использовать функцию omp_set_lock в качестве барьера, то есть вместо директивы #pragma omp barrier (эту директиву нельзя использовать внутри параллельных секций, к которым применяется директива #pragma omp sections). В результате возникнет следующий код.

Некорректно:

omp_lock_t myLock;omp_init_lock(&myLock);#pragma omp parallel sections{ #pragma omp section { ... omp_set_lock(&myLock); ... } #pragma omp section { ... omp_set_lock(&myLock); omp_unset_lock(&myLock); ... }}

В результате выполнения этого фрагмента кода программа иногда будет зависать, а иногда – выполняться нормально. Зависеть это будет от того, какой поток завершается последним. Если последним будет завершаться поток, в котором выполняется блокировка переменной без ее освобождения, программа будет выдавать ожидаемый результат. Во всех остальных случаях будет возникать бесконечное ожидание освобождения переменной, захваченной потоком, работающим с переменной некорректно. Аналогичная ситуация будет возникать и при использовании функции omp_test_lock в цикле (а именно так эту функцию обычно и используют). В этом случае поток будет бесконечно «топтаться на месте», так и не дождавшись освобождения переменной.

Поскольку данная ошибка аналогична предыдущей, корректный вариант кода будет выглядеть так же.

Корректно:

omp_lock_t myLock;omp_init_lock(&myLock);#pragma omp parallel sections{ #pragma omp section { ... omp_set_lock(&myLock); ... omp_unset_lock(&myLock); ... } #pragma omp section { ... omp_set_lock(&myLock); ... omp_unset_lock(&myLock); ... }}







Дата добавления: 2015-02-03; просмотров: 776;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.003 сек.