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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ для Linux. ΠŸΡ€ΠΎΡ„Π΅ΡΡΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 22

Автор ΠœΠ°Ρ€ΠΊ ΠœΠΈΡ‚Ρ‡Π΅Π»Π»

   /* УдаляСм Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΈΠ· списка. */

   job_queue = job_queue->next;

  }


  /* ОсвобоТдаСм сСмафор, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π° с ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒΡŽ ΠΎΠΊΠΎΠ½Ρ‡Π΅Π½Π°. */

  pthread_mutex_unlock(&job_queue_mutex);

  /* Если ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ пуста, Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅ΠΌ ΠΏΠΎΡ‚ΠΎΠΊ. */

  if (next_job == NULL)

   break;

  /* ВыполняСм Π·Π°Π΄Π°Π½ΠΈΠ΅. */

  process_job(next_job);

  /* ΠžΡ‡ΠΈΡΡ‚ΠΊΠ°. */

  free(next_job);

 }

 return NULL;

}

ВсС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ доступа ΠΊ совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΌΡƒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŽ job_queue происходят ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ pthread_mutex_lock() ΠΈ pthread_mutex_unlock(). ΠžΠ±ΡŠΠ΅ΠΊΡ‚ задания, ссылка Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ хранится Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ next_job, обрабатываСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ссылка Π½Π° Π½Π΅Π³ΠΎ удаляСтся ΠΈΠ· ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ, Ρ‡Ρ‚ΠΎ позволяСт ΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠΈΡ‚ΡŒ этот ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ, Ссли ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ пуста (Ρ‚.Π΅. ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ job_queue Ρ€Π°Π²Π΅Π½ NULL), Ρ†ΠΈΠΊΠ» Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ. Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²Π΅Π»ΠΎ Π±Ρ‹ ΠΊ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор Ρ‚Π°ΠΊ ΠΈ остался Π±Ρ‹ Π² Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π½ΠΎΠΌ состоянии ΠΈ Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΠ» Π±Ρ‹ Π½ΠΈ ΠΎΠ΄Π½ΠΎΠΌΡƒ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ Π·Π°Π΄Π°Π½ΠΈΠΉ. ΠœΡ‹ дСйствуСм ΠΈΠ½Π°Ρ‡Π΅: записываСм Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ next_job Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ NULL ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ ΠΈΠ· Ρ†ΠΈΠΊΠ»Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ послС освобоТдСния сСмафора.

Π˜ΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ доступ ΠΊ участку ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π° Π½Π΅ ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Π’ обязанности программиста Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΊΠΎΠ΄ для Π·Π°Ρ…Π²Π°Ρ‚Π° сСмафора ΠΏΠ΅Ρ€Π΅Π΄ доступом ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π΅Π³ΠΎ освобоТдСния. Π’ΠΎΡ‚ ΠΊΠ°ΠΊ. Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ функция, Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‰Π°Ρ Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΊ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ:

void enqueue_job(struct job* new_job) {

 pthread_mutex_lock(&job_queue_mutex);

 new_job->next = job_queue;

 job_queue = new_job;

 pthread_mutex_unlock(&job_queue_mutex);

}

4.4.3. Π’Π·Π°ΠΈΠΌΠΎΠ±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΡ… сСмафоров

Π˜ΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠ΅ сСмафоры ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠΌ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΌ ΠΎΠ΄Π½ΠΎΠΌΡƒ ΠΏΠΎΡ‚ΠΎΠΊΡƒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°. Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ возникновСнию Π½ΠΎΠ²ΠΎΠ³ΠΎ класса ошибок. Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… Π²Π·Π°ΠΈΠΌΠΎΠ±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°ΠΌΠΈ ΠΈΠ»ΠΈ Ρ‚ΡƒΠΏΠΈΠΊΠΎΠ²Ρ‹ΠΌΠΈ ситуациями. Бмысл ошибки Π² Ρ‚ΠΎΠΌ. Ρ‡Ρ‚ΠΎ ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‚ наступлСния события, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π½Π° самом Π΄Π΅Π»Π΅ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚.

ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ°Ρ тупиковая ситуация β€” ΠΊΠΎΠ³Π΄Π° ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡ‚ΠΎΠΊ пытаСтся Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ Ρ‚ΠΎΡ‚ ΠΆΠ΅ самый ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор Π΄Π²Π°ΠΆΠ΄Ρ‹ подряд. Π”Π°Π»ΡŒΠ½Π΅ΠΉΡˆΠΈΠ΅ дСйствия зависят ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора. Π˜Ρ… всСго Ρ‚Ρ€ΠΈ.

β–  Π—Π°Ρ…Π²Π°Ρ‚ быстрого сСмафора (ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ) ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ Π²Π·Π°ΠΈΠΌΠΎΠ±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅. Ѐункция, ΠΎΠ±Ρ€Π°Ρ‰Π°ΡŽΡ‰Π°ΡΡΡ ΠΊ Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½Π½ΠΎΠΌΡƒ сСмафору Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠΎΡ‚ΠΎΠΊ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° сСмафор Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ освобоТдСн. Но сСмафор ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ самому ΠΏΠΎΡ‚ΠΎΠΊΡƒ, поэтому Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ снята.

β–  Π—Π°Ρ…Π²Π°Ρ‚ рСкурсивного сСмафора Π½Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ Π²Π·Π°ΠΈΠΌΠΎΠ±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ΅. Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚, сколько Ρ€Π°Π· функция pthread_mutex_lock() Π±Ρ‹Π»Π° Π²Ρ‹Π·Π²Π°Π½Π° Π² ΠΏΠΎΡ‚ΠΎΠΊΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ сСмафор. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ сСмафор ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ Π½Π΅ΠΌΡƒ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎΠ΅ число Ρ€Π°Π· Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ pthread_mutex_unlock().

β–  ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ систСма Linux ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΡƒ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ сСмафор ΠΈ сигнализируСт ΠΎΠ± этом: ΠΏΡ€ΠΈ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_mutex_lock() возвращаСтся ΠΊΠΎΠ΄ ошибки EDEADLK.

По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π² Linux создаСтся быстрый сСмафор. Π’ Π΄Π²ΡƒΡ… Π΄Ρ€ΡƒΠ³ΠΈΡ… случаях трСбуСтся ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² сСмафора, объявив ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚ΠΈΠΏΠ° pthread_mutexattr_t ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π² ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π½Π΅Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_mutexattr_init(). Π—Π°Ρ‚Π΅ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_mutexattr_setkind_np(). ΠŸΠ΅Ρ€Π²Ρ‹ΠΌ Π΅Π΅ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ являСтся ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² сСмафора; Π²Ρ‚ΠΎΡ€ΠΎΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Ρ€Π°Π²Π΅Π½ PTHREAD_MUTEX_RECURSIVE_NP Π² случаС рСкурсивного сСмафора ΠΈ PTHREAD_MUTEX_ERRORCHECK_NP β€” Π² случаС ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ сСмафора. Π£ΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_mutex_init(), которая создаст сСмафор. ПослС этого Π½ΡƒΠΆΠ½ΠΎ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠ² с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pthread_mutexattr_destroy().

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ»Π»ΡŽΡΡ‚Ρ€ΠΈΡ€ΡƒΠ΅Ρ‚ процСсс создания ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ сСмафора:

pthread_mutexattr_t attr;

pthread_mutex_t mutex;


pthread_mutexattr_init(&attr);

pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);

pthread_mutex_init(&mutex, &attr);

pthread_mutexattr_destroy(&attr);

Как подсказываСт прСфикс "np" (not portable), ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠ΅ сСмафоры рСкурсивного ΠΈ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ Ρ‚ΠΈΠΏΠΎΠ² спСцифичны для Linux ΠΈ нСпСрСносимы Π² Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹Π΅ систСмы. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π½Π΅ рСкомСндуСтся ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ… ΡˆΠΈΡ€ΠΎΠΊΠΎΠ³ΠΎ назначСния.

4.4.4. ΠΠ΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΡ… сСмафоров

Иногда Π½ΡƒΠΆΠ½ΠΎ, Π½Π΅ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½ Π»ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор. Для ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π΅ всСгда ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ пассивного оТидания, вСдь Π·Π° это врСмя ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ³ΠΎ! Ѐункция pthread_mutex_lock() Π½Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ значСния Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° сСмафор Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ освобоТдСн, поэтому ΠΎΠ½Π° Π½Π°ΠΌ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚.

Π’ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ, β€” это функция pthread_mutex_trylock(). Если ΠΎΠ½Π° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ сСмафор свободСн, Ρ‚ΠΎ Π·Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Π΅Π³ΠΎ Ρ‚Π°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ функция pthread_mutex_lock(), возвращая ΠΏΡ€ΠΈ этом 0. Если ΠΆΠ΅ оказываСтся, Ρ‡Ρ‚ΠΎ сСмафор ΡƒΠΆΠ΅ Π·Π°Ρ…Π²Π°Ρ‡Π΅Π½ Π΄Ρ€ΡƒΠ³ΠΈΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠΌ, функция pthread_mutex_trylock() Π½Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, Π° Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ, возвращая ΠΊΠΎΠ΄ ошибки EBUSY. "ΠŸΡ€Π°Π²Π° собствСнности" Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ€ΠΈ этом Π½Π΅ Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚ΡΡ. МоТно ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ сСмафор ΠΏΠΎΠ·Π΄Π½Π΅Π΅.

4.4.5. ΠžΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Ρ‹Π΅ сСмафоры

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

Π’Π°ΠΊΠΎΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ называСтся сСмафором. Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ β€” это счСтчик, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ для синхронизации ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ систСма Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΈ модификация значСния сСмафора ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ бСзопасно ΠΈ Π½Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄ΡƒΡ‚ ΠΊ возникновСнию Π³ΠΎΠ½ΠΊΠΈ.

Π‘Ρ‡Π΅Ρ‚Ρ‡ΠΈΠΊ сСмафора являСтся Π½Π΅ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ Ρ†Π΅Π»Ρ‹ΠΌ числом. Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π΄Π²Π΅ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ.

β–  ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ оТидания (wait) ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ. Если счСтчик ΡƒΠΆΠ΅ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ, опСрация блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика Π½Π΅ станСт ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ (вслСдствиС дСйствий, выполняСмых Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ). ПослС снятия Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ сСмафора ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ ΠΈ опСрация Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ.

β–  ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΡ установки (post) ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ. Если Π΄ΠΎ этого счСтчик Π±Ρ‹Π» Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ ΠΈ сущСствовали ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π² ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ оТидания Π΄Π°Π½Π½ΠΎΠ³ΠΎ сСмафора, ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π½ΠΈΡ… разблокируСтся ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ свою ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ (Ρ‚.Π΅. счСтчик сСмафора снова становится Ρ€Π°Π²Π½Ρ‹ΠΌ Π½ΡƒΠ»ΡŽ).

Π’ Linux ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ Π΄Π²Π΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‰ΠΈΠ΅ΡΡ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСмафоров. Π’Π°, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ опишСм Π½ΠΈΠΆΠ΅, соотвСтствуСт стандарту POSIX. Π’Π°ΠΊΠΈΠ΅ сСмафоры ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ для ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΠΈ взаимодСйствия ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². Другая рСализация, слуТащая цСлям мСТпроцСссного взаимодСйствия, рассмотрСна Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ 5.2, "Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€Ρ‹ для процСссов". ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с сСмафорами Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Ρ„Π°ΠΉΠ» <semaphore.h>.

Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ прСдставляСтся ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Ρ‚ΠΈΠΏΠ° sem_t. Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ слСдуСт ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sem_init(), ΠΏΠ΅Ρ€Π΅Π΄Π°Π² Π΅ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ сСмафора. Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ,[14] Π° Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ β€” это Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика сСмафора.

Π§Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ оТидания сСмафора, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ sem_wait(). Ѐункция sem_post() устанавливаСт сСмафор. Π•ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ функция sem_trywait(), Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰Π°Ρ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ оТидания. Она Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ pthread_mutex_trylock(): Ссли опСрация оТидания ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈΠ·-Π·Π° Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ счСтчик сСмафора Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ, функция Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ, возвращая ΠΊΠΎΠ΄ ошибки EAGAIN.

Π’ Linux имССтся функция sem_getvalue(), ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰Π°Ρ ΡƒΠ·Π½Π°Ρ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика сСмафора. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ помСщаСтся Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚ΠΈΠΏΠ° int, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ссылаСтся Π²Ρ‚ΠΎΡ€ΠΎΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. НС ΠΏΡ‹Ρ‚Π°ΠΉΡ‚Π΅ΡΡŒ Π½Π° основании Π΄Π°Π½Π½ΠΎΠ³ΠΎ значСния ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ, стоит Π»ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ оТидания ΠΈΠ»ΠΈ установки, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ это ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ возникновСнию Π³ΠΎΠ½ΠΊΠΈ: Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ способСн ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ счСтчик сСмафора ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sem_getvalue() ΠΈ ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с сСмафором. ДовСряйтС Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹ΠΌ функциям sem_wait() ΠΈ sem_post().