Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX: взаимодСйствиС процСссов». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 49

Автор Уильям БтивСнс

Рис. 8.1. ВрСмСнная Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ· листинга 8.9


Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π΄Π²ΡƒΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²

10-13 Π‘ΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Π΄Π²Π° ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… выполняСт Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ thread1, Π° Π²Ρ‚ΠΎΡ€ΠΎΠΉ β€” thread2. ПослС создания ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ дСлаСтся ΠΏΠ°ΡƒΠ·Π° Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ Π² ΠΎΠ΄Π½Ρƒ сСкунду, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ успСл Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ рСсурс Π½Π° Ρ‡Ρ‚Π΅Π½ΠΈΠ΅. 

ОТиданиС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²

14-23 ΠœΡ‹ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ провСряСм, Ρ‡Ρ‚ΠΎ Π΅Π³ΠΎ статус ΠΈΠΌΠ΅Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ PTHREAD_CANCEL. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΆΠ΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ провСряСм, Ρ‡Ρ‚ΠΎ Π΅Π³ΠΎ статус прСдставляСт собой Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚Ρ€Π΅Ρ… счСтчиков Π² структурС pthread_rwlock_t ΠΈ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°Π΅ΠΌ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ.

Листинг 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 ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ-ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΏΡ€ΠΈ этом Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½Π΅ слСдуСт. Если этот Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π±ΡƒΠ΄Π΅Ρ‚ сначала Π²Ρ‹Π·Π²Π°Π½, Π° Π·Π°Ρ‚Π΅ΠΌ ΡƒΠ΄Π°Π»Π΅Π½.

Если ΠΏΠΎΡ‚ΠΎΠΊ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½ ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ pthread_cond_wait, Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΈΠ· Π½Π΅Π΅ Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚. ВмСсто этого Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½Ρ‹ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ (послС блокирования ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, ΠΊΠ°ΠΊ ΠΌΡ‹ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠ»ΠΈ Π² ΠΏΡƒΠ½ΠΊΡ‚Π΅ 3 Ρ‡ΡƒΡ‚ΡŒ Π²Ρ‹ΡˆΠ΅).

Π’ листингС 8.10 ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ тСкст Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ rwlock_cancelrdwait, ΡΠ²Π»ΡΡŽΡ‰Π΅ΠΉΡΡ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ-очиститСлСм для phtread_rwlock_rdlock.

Листинг 8.10. Ѐункция rwlock_cancelrdwait: ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ чтСния

//my_rwlock_cancel/pthread_rwlock_rdlock.с

3  static void

4  rwlock_cancelrdwait(void *arg)

5  {

6   pthread_rwlock_t *rw;

7   rw = arg;

8   rw->rw_nwaitreaders--;

9   pthread_mutex_unlock(&rw->rw_mutex);

10 }

8-9 Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ rw_nwaitreaders ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ, Π° Π·Π°Ρ‚Π΅ΠΌ разблокируСтся Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅. Π­Ρ‚ΠΎ состояниС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ восстановлСно ΠΏΡ€ΠΈ ΠΎΡ‚ΠΌΠ΅Π½Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°.

Аналогично ΠΌΡ‹ исправим тСкст Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_rwlock_wrlock ΠΈΠ· листинга 8.6. Π‘Π½Π°Ρ‡Π°Π»Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π΄Π²Π΅ Π½ΠΎΠ²Ρ‹Π΅ строки рядом с Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ pthread_cond_wait:

  rw->rw_nwaitreaders++;

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

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

+ pthread_cleanup_pop(0);

  rw->rw_nwaitreaders--;

Π’ листингС 8.11 ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ тСкст Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ rwlock_cancelwrwait, ΡΠ²Π»ΡΡŽΡ‰Π΅ΠΉΡΡ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ-очиститСлСм для запроса Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π½Π° запись.

Листинг 8.11. Ѐункция rwlock_cancelwrwait: ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ для Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ записи

//my_rwlock_cancel/pthread_rwlock_wrlock.с

3  static void

4  rwlock_cancelwrwait(void *arg)

5  {

6   pthread_rwlock_t *rw;

7   rw = arg;

8   rw->rw_nwaitwriters––;

9   pthread_mutex_unlock(&rw->rw_mutex);

10 }

8-9 Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ rw_nwaitwriters ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ, ΠΈ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ разблокируСтся. ΠŸΡ€ΠΈ запускС нашСй тСстовой ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ· листинга 8.9 с этими Π½ΠΎΠ²Ρ‹ΠΌΠΈ функциями ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹:

solaris %testcancel

thread1() got a read lock

thread2() trying to obtain a write lock

rw_refcount = 0, rw_nwaitreaders = 0, rw_nwaitwriters = 0

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‚Ρ€ΠΈ счСтчика ΠΈΠΌΠ΅ΡŽΡ‚ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ значСния, ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ возвращаСтся ΠΈΠ· Π²Ρ‹Π·ΠΎΠ²Π° pthread_rwlock_unlock, Π° функция pthread_rwlock_destroy Π½Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ EBUSY.

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•

Π­Ρ‚ΠΎΡ‚ Ρ€Π°Π·Π΄Π΅Π» прСдставляСт собой ΠΎΠ±Π·ΠΎΡ€ вопросов, связанных с ΠΎΡ‚ΠΌΠ΅Π½ΠΎΠΉ выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Для Π±ΠΎΠ»Π΅Π΅ Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ изучСния этих ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊ Ρ€Π°Π·Π΄Π΅Π»Ρƒ 5.3 ΠΊΠ½ΠΈΠ³ΠΈ [3].

8.6. РСзюмС

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ чтСния-записи ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π»ΡƒΡ‡ΡˆΠ΅ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, Ρ‡Π΅ΠΌ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ Π²Π·Π°ΠΈΠΌΠ½Ρ‹Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, Ссли Π·Π°Ρ‰ΠΈΡ‰Π°Π΅ΠΌΡ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Ρ‡Π°Ρ‰Π΅ ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ, Ρ‡Π΅ΠΌ ΠΈΠ·ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ. Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с этими Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°ΠΌΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ стандартом Unix 98, ΠΈΡ… ΠΌΡ‹ ΠΈ описываСм Π² этой Π³Π»Π°Π²Π΅. АналогичныС ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Π΅ ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΡΠ²ΠΈΡ‚ΡŒΡΡ Π² Π½ΠΎΠ²ΠΎΠΉ вСрсии стандарта Posix. По Π²ΠΈΠ΄Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ функциям для Ρ€Π°Π±ΠΎΡ‚Ρ‹ со Π²Π·Π°ΠΈΠΌΠ½Ρ‹ΠΌΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ (Π³Π»Π°Π²Π° 7).

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ чтСния-записи Π»Π΅Π³ΠΊΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ с использованиСм Π²Π·Π°ΠΈΠΌΠ½Ρ‹Ρ… ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ ΠΈ условных ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…. ΠœΡ‹ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ. Π’ нашСй вСрсии ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΈΠΌΠ΅ΡŽΡ‚ Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π½ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π΄Ρ€ΡƒΠ³ΠΈΡ… вСрсиях ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚Π΄Π°Π½ ΠΈ ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ.

ΠŸΠΎΡ‚ΠΎΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚ΠΌΠ΅Π½Π΅Π½Ρ‹ Π² Ρ‚ΠΎ врСмя, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ΠΈ находятся Π² Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌ состоянии, Π² частности ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ pthread_cond_wait, ΠΈ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ нашСй Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΡ‹ ΡƒΠ±Π΅Π΄ΠΈΠ»ΠΈΡΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ этом ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹. Π Π΅ΡˆΠΈΡ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡƒΡ‚Π΅ΠΌ использования ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ²-очиститСлСй.

УпраТнСния

1. Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚Π΅ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 8.4 Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΈΠΌΠ΅Π»ΠΈ ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅, Π° Π½Π΅ Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ.