проблемы с pthread_rwlock_wrlock и pthread_rwlock_wrlock - PullRequest
3 голосов
/ 06 января 2012
#include <stdio.h>
#include <errno.h>
#include <pthread.h>

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

void *func(void *arg)
{
        while (1) {
                printf("begin\n");
                pthread_rwlock_wrlock(&rwlock);
                printf("fall through wrlock\n");
                pthread_rwlock_wrlock(&rwlock);
                printf("fall through wrlock\n");
                pthread_rwlock_unlock(&rwlock);
                printf("fall through unlock\n");
                pthread_rwlock_unlock(&rwlock);
                printf("end\n");
        }
}

int main()
{
        pthread_t thd;
        pthread_create(&thd, NULL, func, NULL);

        sleep(100);
}
~                

Я пишу код выше на UBUNTU 10.04 и запускаю, он просто выводит

root @ ubuntu: ~ # ./a.out

begin
fall through wrlock
fall through wrlock
fall through unlock
end
begin

.. и, наконец, блокируетздесь

Почему он не блокируется, когда первый раз
второй
pthread_rwlock_wrlock (& ​​rwlock)
называется

1 Ответ

8 голосов
/ 06 января 2012

Результаты не определены, если вызывающий поток удерживает блокировку чтения-записи (будь то блокировку чтения или записи) во время вызова.

Это с страница Open Group на pthread_rwlock_wrlock.

То, что вы делаете, не определено, по крайней мере, в этой версии спецификации.Вам повезло, что злобные обезьяны не влетели в окно и не забили вас до смерти: -)


В любом случае вам действительно следует проверять код возврата во всех ваших функциях pthread.Они могут потерпеть неудачу, и вы действительно не хотите продолжать, предполагая, что у вас есть блокировка, когда на самом деле вы не делаете, , так как этот тип сводит на нет полезность блокировок.

Эта же страница связана с указанными выше состояниями:

Функции pthread_rwlock_wrlock() и pthread_rwlock_trywrlock() могут не работать, если:
[EINVAL] - значение, указанное в rwlock, необратитесь к инициализированному объекту блокировки чтения-записи.
[EDEADLK] - текущий поток уже владеет блокировкой чтения-записи для записи или чтения.

Я бы проверил, действительно ли вы получаете код ошибки EDEADLK.Этот код ошибки возможен даже в последних выпусках потоков POSIX , где, как указывает Немо в комментарии, «неопределенная» формулировка была удалена.


Одна вещьвсе еще беспокойство однако.В последней спецификации указывается, что «вызывающий поток может тупиковый, если во время вызова он удерживает блокировку чтения-записи» (мой жирный).

Я вижу это как фактический тупик, т. Е. Поток полностью блокируется.В разделе кода ошибки EDEADLK также говорится, что "pthread_rwlock_wrlock() функция может завершиться ошибкой, если ..." (опять же, мой жирный шрифт).

Оба эти утверждения имеют слово "ласка"может "в них, так что до сих пор неясно, что произойдет в любой конкретной ситуации.Может быть (без каламбура), что это было оставлено неуказанным, потому что некоторые реализации вели себя по-разному (не всегда легко обнаружить тупиковую ситуацию заранее), хотя это чистое предположение с моей стороны.

Суть, если вы знаю у вас есть какая-то рекурсивная блокировка (где вы можете разблокировать безнаказанно), не делайте этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...