Чтение онлайн

на главную - закладки

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:
Листинг 8.9. Тестовая программа, иллюстрирующая отмену выполнения потока

//my_rwlock_cancel/testcancel.с

1 #include "unpipc.h"

2 #include "pthread_rwlock.h"

3 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

4 pthread_t tid1, tid2;

5 void *thread1(void *), *thread2(void *);

6 int

7 main(int argc, char **argv)

8 {

9 void *status;

10 Set_concurrency(2);

11 Pthread_create(&tid1, NULL, thread1, NULL);

12 sleep(1); /* даем первому потоку возможность получить блокировку */

13 Pthread_create(&tid2, NULL, thread2, NULL);

14 Pthread_join(tid2, &status);

15 if (status != PTHREAD_CANCELED)

16 printf("thread2 status = %p\n", status);

17 Pthread_join(tid1, &status);

18 if (status != NULL)

19 printf("thread1 status = %p\n", status);

20 printf("rw_refcount = %d, rw_nwaitreaders = %d, rw_nwaitwriters = %d\n",

21 rwlock.rw_refcount, rwlock.rw_nwaitreaders,

22 rwlock.rw_nwaitwriters);

23 Pthread_rwlock_destroy(&rwlock);

24 exit(0);

25 }

26 void *

27 thread1(void *arg)

28 {

29 Pthread_rwlock_rdlock(&rwlock);

30 printf("thread1 got a read lock\n");

31 sleep(3); /* даем второму потоку возможность заблокироваться при вызове pthread_rwlock_wrlock */

32 pthread_cancel(tid2);

33 sleep(3);

34 Pthread_rwlock_unlock(&rwlock);

35 return(NULL);

36 }

37 void *

38 thread2(void *arg)

39 {

40 printf("thread2 trying to obtain a write lock\n"):

41 Pthread_rwlock_wrlock(&rwlock);

42 printf("thread2 got a write lock\n"); /* не будет выполнено */

43 sleep(1);

44 Pthread_rwlock_unlock(&rwlock);

45 return(NULL);

46 }

Функция thread1

26-36 Поток получает блокировку на чтение и ждет 3 секунды. Эта пауза дает возможность другому потоку вызвать pthread_rwlock_wrlock и заблокироваться при вызове pthread_cond_wait, поскольку блокировка на запись не может быть установлена из-за наличия блокировки на чтение. Затем первый поток вызывает pthread_cancel для отмены выполнения второго потока, ждет 3 секунды, освобождает блокировку на чтение и завершает работу.

Функция thread2

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

При запуске этой программы с использованием функций из предыдущего раздела мы получим следующий результат:

solaris % testcancel

thread1 got a read lock

thread2 trying to obtain a write lock

и мы никогда не вернемся к приглашению интерпретатора. Программа зависнет. Произошло вот что:

1. Второй поток вызвал pthread_rwlock_wrlock (листинг 8.6), которая была заблокирована в вызове pthread_cond_wait.

2. Первый поток вернулся из вызова slеер(3) и вызвал pthread_cancel.

3. Второй поток был отменен и завершил работу. При отмене потока, заблокированного в ожидании сигнала по условной переменной, взаимное исключение блокируется до вызова первого обработчика-очистителя. (Мы не устанавливали обработчик, но взаимное исключение все равно блокируется до завершения потока.) Следовательно, при отмене выполнения второго потока взаимное исключение осталось заблокированным и значение rw_nwaitwriters в листинге 8.6 было увеличено.

4. Первый поток вызывает pthread_rwlock_unlock и блокируется навсегда при вызове pthread_mutex_lock (листинг 8.8), потому что взаимное исключение все еще заблокировано отмененным потоком.

Если мы уберем вызов pthread_rwlock_unlock в функции thread1, функция main выведет вот что:

rw_refcount = 1, rw_nwaitreaders = 0, rw_nwaitwriters = 1

pthread_rwlock_destroy error: Device busy
 

Первый счетчик имеет значение 1, поскольку мы удалили вызов pthread_rwlock_ unlock, а последний счетчик имеет значение 1, поскольку он был увеличен вторым потоком до того, как тот был отменен.

Исправить эту проблему просто. Сначала добавим две строки к функции pthread_rwlock_rdlock в листинге 8.4. Строки отмечены знаком +:

rw->rw_nwaitreaders++;

+ pthread_cleanup_push(rwlock_cancelrdwait, (void *) rw);

result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex);

+ pthread_cleanup_pop(0);

rw->rw_nwaitreaders++;

Первая новая строка устанавливает обработчик-очиститель (функцию rwlock_cancelrdwait), а его единственным аргументом является указатель rw. После возвращения из pthread_cond_wait вторая новая строка удаляет обработчик. Аргумент функции pthread_cleanup_pop означает, что функцию-обработчик при этом вызывать не следует. Если этот аргумент имеет ненулевое значение, обработчик будет сначала вызван, а затем удален.

Поделиться:
Популярные книги

Иной. Том 1. Школа на краю пустыни

Amazerak
1. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.75
рейтинг книги
Иной. Том 1. Школа на краю пустыни

Стражи душ

Кас Маркус
4. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Стражи душ

Я уже барон

Дрейк Сириус
2. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я уже барон

Черный Маг Императора 5

Герда Александр
5. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 5

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Мастер 11

Чащин Валерий
11. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 11

Эволюционер из трущоб

Панарин Антон
1. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб

На границе империй. Том 10. Часть 9

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 9

Локки 9. Потомок бога

Решетов Евгений Валерьевич
9. Локки
Фантастика:
фэнтези
попаданцы
героическая фантастика
боевая фантастика
5.00
рейтинг книги
Локки 9. Потомок бога

Законы Рода. Том 3

Мельник Андрей
3. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 3

Адвокат Империи 4

Карелин Сергей Витальевич
4. Адвокат империи
Фантастика:
городское фэнтези
аниме
дорама
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Адвокат Империи 4

Барон меняет правила

Ренгач Евгений
2. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон меняет правила

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Неучтенный элемент. Том 6

NikL
6. Антимаг. Вне системы
Фантастика:
фэнтези
5.25
рейтинг книги
Неучтенный элемент. Том 6