Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 51



Иногда, тем не менее, поток может не захотеть блокироваться, желая вместо этого просто узнать, доступна ли нужная блокировка. Для этого и существуют версии функций, содержащие в имени «try» («проверка»). Важно отметить, что «проверочные» версии получат блокировку, если она доступна, но если нет, тогда они не будут блокированы, а только возвратят код ошибки. Причина, по которой они должны получать блокировку, если она доступна, очень проста. Предположим, что поток хочет получить блокировку на чтение, но не хочет ждать, если блокировка окажется недоступной. Поток вызывает функцию pthread_rwlock_tryrdlock(), и оказывается, что блокировка доступна. Если бы функция pthread_rwlock_tryrdlock() не захватывала доступную блокировку немедленно, могли бы произойти неприятные вещи — наш поток мог бы быть, к примеру, вытеснен другим потоком, а тот, в свою очередь, мог бы блокировать нужный нам ресурс. Поскольку первому потоку фактически не была предоставлена блокировка, после возобновления ему придется вызывать pthread_rwlock_rdlock(), и вот теперь он будет заблокирован, поскольку ресурс более недоступен. Иными словами, в такой ситуации даже поток, не желающий блокироваться и поэтому вызывающий «проверочную» версию, по-прежнему может быть заблокирован!

Наконец, независимо от того, как блокировка нами применялась, нам необходим способ ее освобождения:

>int pthread_rwlock_unlock(pthread_rwlock_t* lock);

После того как поток выполнил нужную операцию с ресурсом, он освобождает блокировку, вызывая функцию pthread_rwlock_unlock(). Если блокировка теперь становится доступной в режиме, который запрошен и ожидается другим потоком, то этот ждущий поток будет переведен в состояние готовности (READY).

Отметим, что мы не смогли бы реализовать такую форму синхронизации только с помощью мутекса. Мутекс рассчитан только на один поток, что было бы хорошо в случае записи (чтобы только один поток мог использовать ресурс в определенный момент времени), но оплошал бы в случае считывания, потому что не допустил бы к ресурсу более чем одного «читателя». Семафор также был бы бесполезен, потому что нельзя было бы отличить два режима доступа — применение семафора могло бы обеспечить доступ нескольких «читателей», но если бы семафором попытался завладеть «писатель», его вызов ничем бы не отличался от вызова «читателей», что вызвало бы некрасивую ситуацию с множеством «читателей» и множеством же «писателей»!