Глядя на справочную страницу для pthread_rwlock_wrlock()
, я вижу, что там написано:
В случае успеха функция pthread_rwlock_wrlock()
возвращает ноль;в противном случае возвращается номер ошибки, указывающий на ошибку.
[…]
Функция pthread_rwlock_wrlock()
может завершиться ошибкой, если:
EDEADLK
Текущий поток уже владеет блокировкой чтения-записи для записи или чтения.
Насколько я понимаю, EDEADLK
никогда не используется для указания цепочек, включающих несколько потоков, ожидающих ресурсы друг друга (ипо моим наблюдениям, такие тупики действительно приводят к замораживанию, а не EDEADLK
).Кажется, это указывает исключительно на то, что поток запрашивает ресурс, уже удерживаемый текущим потоком , что является условием, которое я хочу проверить.
Если я неправильно понял документациюПожалуйста, дайте мне знать. В противном случае решение будет просто позвонить pthread_rwlock_wrlock()
.Должно произойти одно из следующих действий:
- Блокируется, поскольку ресурс удерживается другим потоком.Когда мы снова побежим, мы будем держать замок.Обычный бизнес.
- Возвращает ноль (успех), потому что мы только что получили блокировку (которую мы раньше не держали).Обычный бизнес.
- Возвращает
EDEADLK
, потому что мы уже держим замок.Не нужно повторно запрашивать, но мы могли бы рассмотреть это, когда снимаем блокировку - это зависит от кода, о котором идет речь, см. Ниже - Возвращает некоторую другую ошибку, указывающую, что что-то действительно пошло не так.То же, что и при любой другой операции блокировки.
Может иметь смысл отслеживать количество раз, когда мы получили блокировку и получили EDEADLK
.Исходя из ответа Джила Гамильтона, глубина блокировки будет работать для нас:
- Сбросьте глубину блокировки до 0, когда мы получим блокировку.
- Увеличивайте глубину блокировки каждый раз на 1мы получаем
EDEADLK
. - Сопоставьте каждую попытку получения блокировки со следующим: Если глубина блокировки равна 0, снимите блокировку.Иначе уменьшите глубину блокировки.
Это должно быть поточно-ориентированным без дальнейшей синхронизации, так как глубина блокировки эффективно защищена замком, к которому она относится (мы касаемся только при удерживании замка).
Предупреждение: , если текущий поток уже удерживает блокировку чтения (а другие этого не делают), он также сообщит о том, что он «уже заблокирован».Необходимы дальнейшие тесты, чтобы определить, действительно ли текущая блокировка является блокировкой записи.Если несколько потоков, в том числе текущий, удерживают блокировку чтения, я не знаю, если попытка получить блокировку записи вернет EDEADLK
или остановит поток.Эта часть требует дополнительной работы ...