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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX: Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСтСвых ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 197

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

НСкоторыС систСмы (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Solaris) ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ константу PTHREAD_MUTEX_INITIALIZER ΠΊΠ°ΠΊ 0. Если данная инициализация Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡƒΡ‰Π΅Π½Π°, это Π½ΠΈ Π½Π° Ρ‡Ρ‚ΠΎ Π½Π΅ повлияСт, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ статичСски Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Π΅ΠΌΡ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ всС Ρ€Π°Π²Π½ΠΎ автоматичСски ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π½ΡƒΠ»Π΅ΠΌ. Но для Π΄Ρ€ΡƒΠ³ΠΈΡ… систСм Ρ‚Π°ΠΊΠΎΠΉ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ Π΄Π°Ρ‚ΡŒ нСльзя β€” Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² Digital Unix константа ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ нСнулСвая.

Π’ листингС 26.12 ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° исправлСнная вСрсия листинга 26.11, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ΄Π½ΠΎ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ для блокирования счСтчика ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с двумя ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ.

Листинг 26.12. Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π½Π°Ρ вСрсия листинга 26.11, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π°Ρ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ для Π·Π°Ρ‰ΠΈΡ‚Ρ‹ совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ

//threads/examplС01.с

 1 #include "unpthread.h"


 2 #define NLOOP 5000


 3 int counter; /* увСличиваСтся ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ */

 4 pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;


 5 void *doit(void*);


 6 int

 7 main(int argc, char **argv)

 8 {

 9  pthread_t tidA, tidB;


10  Pthread_create(&tidA, NULL, &doit, NULL);

11  Pthread_create(&tidB, NULL, &doit, NULL);


12  /* ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ ΠΎΠ±ΠΎΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

13  Pthread_join(tidA, NULL);

14  Pthread_join(tidB, NULL);


15  exit(0);

16 }


17 void*

18 doit(void *vptr)

19 {

20  int i, val;


21  /*

22   * ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ считываСт, Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ ΠΈ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ счСтчик NLOOP Ρ€Π°Π·.

23   * Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²ΠΎΠ·Ρ€Π°ΡΡ‚Π°Ρ‚ΡŒ ΠΌΠΎΠ½ΠΎΡ‚ΠΎΠ½Π½ΠΎ.

24   */


25  for (i = 0; i < NLOOP; i++) {

26   Pthread_mutex_lock(&counter_mutex);


27   val = counter;

28   printf(%d: %d\n", pthread_self(), val + 1);

29   counter = val + 1;


30   Pthread_mutex_unlock(&counter_mutex);

31  }


32  return(NULL);

33 }

ΠœΡ‹ объявляСм Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ с ΠΈΠΌΠ΅Π½Π΅ΠΌ counter_mutex. Π­Ρ‚ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ Π½Π° Ρ‚ΠΎ врСмя, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ counter. Когда ΠΌΡ‹ запускали эту ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ всСгда Π±Ρ‹Π» ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ: Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π»ΠΎΡΡŒ ΠΌΠΎΠ½ΠΎΡ‚ΠΎΠ½Π½ΠΎ, Π° Π΅Π΅ ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ всСгда ΠΎΠΊΠ°Π·Ρ‹Π²Π°Π»ΠΎΡΡŒ Ρ€Π°Π²Π½Ρ‹ΠΌ 10 000.

Насколько ΡΠ΅Ρ€ΡŒΠ΅Π·Π½ΠΎΠΉ являСтся Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ°, связанная с использованиСм Π²Π·Π°ΠΈΠΌΠ½Ρ‹Ρ… ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ? ΠœΡ‹ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Π΅ Π² листингах 26.11 ΠΈ 26.12, Π·Π°ΠΌΠ΅Π½ΠΈΠ² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ NLOOP Π½Π° 50 000 (вмСсто исходного значСния 5000), ΠΈ засСкли врСмя, Π½Π°ΠΏΡ€Π°Π²ΠΈΠ² Π²Ρ‹Π²ΠΎΠ΄ Π½Π° устройство /dev/null. ВрСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ процСссора Π² случаС ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ вСрсии, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΉ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ»ΠΎΡΡŒ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ вСрсии Π±Π΅Π· Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π½Π° 10 %. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ использованиС Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π½Π΅ связано со Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΈΠ·Π΄Π΅Ρ€ΠΆΠΊΠ°ΠΌΠΈ.

26.8. УсловныС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅

Π’Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ позволяСт ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ доступ ΠΊ совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ (раздСляСмой) ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π½ΠΎ для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ пСрСвСсти ΠΏΠΎΡ‚ΠΎΠΊ Π² состояниС оТидания (спящСС состояниС) Π΄ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° выполнСния Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ условия, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ. ΠŸΡ€ΠΎΠ΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ сказанноС Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅. ВСрнСмся ΠΊ Π½Π°ΡˆΠ΅ΠΌΡƒ Π²Π΅Π±-ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ ΠΈΠ· Ρ€Π°Π·Π΄Π΅Π»Π° 26.6 ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Solaris thr_join Π½Π° pthread_join. Но ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ pthread_join Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ Π·Π½Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΎΡΡŒ. Π‘Π½Π°Ρ‡Π°Π»Π° ΠΌΡ‹ объявляСм Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ, которая слуТит счСтчиком количСства Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ²ΡˆΠΈΡ…ΡΡ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΡƒΠ΅ΠΌ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ доступом ΠΊ Π½Π΅ΠΉ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ³ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ.

int ndone; /* количСство ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ²ΡˆΠΈΡ… Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ */

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΏΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ своСго выполнСния ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π» этот счСтчик Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.

void* do_get_read(void *vptr) {

 ...


 Pthread_mutex_lock(&ndone_mutex);

 ndone++;

 Pthread_mutex_unlock(&ndone_mutex);


 return(fptr); /* Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠ° */

}

Но ΠΊΠ°ΠΊΠΈΠΌ ΠΏΡ€ΠΈ этом получаСтся основной Ρ†ΠΈΠΊΠ»? Π’Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ постоянно Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΎ основным Ρ†ΠΈΠΊΠ»ΠΎΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ провСряСт, ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΠΈ своС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅.

while (nlefttoread > 0) {

 while (nconn < maxnconn && nlefttoconn > 0) {

  /* Π½Π°Ρ…ΠΎΠ΄ΠΈΠΌ Ρ„Π°ΠΉΠ» для чтСния */

  ...

 }

 /* ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ Π»ΠΈ ΠΏΠΎΡ‚ΠΎΠΊ */

 Pthread_mutex_lock(&ndone_mutex);

 if (ndone > 0) {

  for (i =0; i < nfiles; i++) {

   if (file[i].f_flags & F_DONE) {

    Pthread_join(file[i].f_tid, (void**)&fptr);

    /* обновляСм file[i] для Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° */

    ...

   }

  }

 }

 Pthread_mutex_unlock(&ndone_mutex);

}

Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² спящСС состояниС, Π° просто Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² Ρ†ΠΈΠΊΠ», провСряя ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ndone. Π­Ρ‚ΠΎΡ‚ процСсс называСтся опросом (polling) ΠΈ рассматриваСтся ΠΊΠ°ΠΊ пустая Ρ‚Ρ€Π°Ρ‚Π° Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ процСссора.

Нам Π½ΡƒΠΆΠ΅Π½ ΠΌΠ΅Ρ‚ΠΎΠ΄, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π³Π»Π°Π²Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» ΠΌΠΎΠ³ Π±Ρ‹ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ Π² состояниС оТидания, ΠΏΠΎΠΊΠ° ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π½Π΅ оповСстит Π΅Π³ΠΎ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ какая-Π»ΠΈΠ±ΠΎ Π·Π°Π΄Π°Ρ‡Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π°. Π­Ρ‚Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ обСспСчиваСтся использованиСм условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ (conditional variable) вмСстС со Π²Π·Π°ΠΈΠΌΠ½Ρ‹ΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ. Π’Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ блокирования, Π° условная пСрСмСнная обСспСчиваСт ΡΠΈΠ³Π½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ.

Π’ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Ρ… Pthreads условная пСрСмСнная β€” это пСрСмСнная Ρ‚ΠΈΠΏΠ° pthread_cond_t. Π’Π°ΠΊΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… Π΄Π²ΡƒΡ… функциях:

#include <pthread.h>


int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);

int pthread_cond_signal(pthread_cond_t *cptr);

ОбС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚: 0 Π² случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ выполнСния, ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Exxx Π² случаС ошибки

Π‘Π»ΠΎΠ²ΠΎ signal Π² Π½Π°Π·Π²Π°Π½ΠΈΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ ΠΊ сигналам Unix SIGxxx.

ΠŸΡ€ΠΎΡ‰Π΅ всСго ΠΎΠ±ΡŠΡΡΠ½ΠΈΡ‚ΡŒ дСйствиС этих Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅. ВСрнСмся ΠΊ Π½Π°ΡˆΠ΅ΠΌΡƒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ Π²Π΅Π±-ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°. Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ ndone Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ассоциируСтся ΠΈ с условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, ΠΈ с Π²Π·Π°ΠΈΠΌΠ½Ρ‹ΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ:

int ndone;

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER;

ΠŸΠΎΡ‚ΠΎΠΊ ΠΎΠΏΠΎΠ²Π΅Ρ‰Π°Π΅Ρ‚ Π³Π»Π°Π²Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» ΠΎ своСм Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ, увСличивая Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика, ΠΏΠΎΠΊΠ° Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ Π΄Π°Π½Π½ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ (Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΎ ΠΈΠΌ), ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΡƒΡΠ»ΠΎΠ²Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ для сигнализации.

Pthread_mutex_lock(&ndone_mutex);

ndone++;

Pthread_cond_signal(&ndone_cond);

Pthread_mutex_unlock(&ndone_mutex);

Π—Π°Ρ‚Π΅ΠΌ основной Ρ†ΠΈΠΊΠ» блокируСтся Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_cond_wait, оТидая оповСщСния ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠ°:

while (nlefttoread > 0) {

 while (nconn < maxnconn && nlefttoconn > 0) {

  /* Π½Π°Ρ…ΠΎΠ΄ΠΈΠΌ Ρ„Π°ΠΉΠ» для чтСния */

  ...

 }


 /* Π–Π΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ выполнСния ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° */

 Pthread_mutex_lock(&ndone_mutex);

 while (ndone == 0)

  Pthread_cond_wait(&ndone_cond, &ndone_mutex);


 for (i = 0; i < nfiles; i++) {

  if (file[i].f_flags & F_DONE) {

   Pthread_join(file[i].f_tid, (void**)&fptr);


   /* обновляСм file[i] для Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° */

   ...

  }

 }

 Pthread_mutex_unlock(&ndone_mutex);

}

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ пСрСмСнная ndone ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ провСряСтся, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅. Π’ΠΎΠ³Π΄Π°, Ссли Π½Π΅ трСбуСтся Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ дСйствиС, вызываСтся функция pthread_cond_wait. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² состояниС оТидания, ΠΈ разблокируСтся Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Π»ΠΎ этому ΠΏΠΎΡ‚ΠΎΠΊΡƒ. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠΎΠ³Π΄Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ возвращаСтся ΠΏΠΎΡ‚ΠΎΠΊΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ pthread_cond_wait (послС Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ поступил сигнал ΠΎΡ‚ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°), ΠΎΠ½ снова Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ всСгда связано с условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ? «УсловиС» ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ прСдставляСт собой Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ совмСстно нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ. Π’Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ трСбуСтся для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΈ ΠΌΠΎΠ³Π»ΠΈ Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. НапримСр, Ссли Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΊΠΎΠ΄Π°, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌ Ρ€Π°Π½Π΅Π΅, отсутствовало Π±Ρ‹ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π² Π³Π»Π°Π²Π½ΠΎΠΌ Ρ†ΠΈΠΊΠ»Π΅ выглядСла Π±Ρ‹ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

/* Π–Π΄Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ выполнСния ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ»ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

while (ndone == 0)

 Pthread_cond_wait(&ndone_cond, &ndone_mutex);

Но ΠΏΡ€ΠΈ этом сущСствуСт Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ послСдний ΠΏΠΎΡ‚ΠΎΠΊ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ndone послС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π³Π»Π°Π²Π½Ρ‹ΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ условия ndone == 0, Π½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_cond_wait. Если это происходит, Ρ‚ΠΎ послСдний «сигнал» тСряСтся, ΠΈ основной Ρ†ΠΈΠΊΠ» оказываСтся Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ навсСгда, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ ΠΆΠ΄Π°Ρ‚ΡŒ события, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚.