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

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

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

Но вСрнСмся ΠΊ Π½Π°ΡˆΠ΅ΠΌΡƒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ. МоТно ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сСмафора потоковая функция провСряла, сколько Π·Π°Π΄Π°Π½ΠΈΠΉ находится Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. ИзмСнСнная вСрсия ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° Π² листингС 4.12.

Листинг 4.12. (job-queue3.c) Π Π°Π±ΠΎΡ‚Π° с ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒΡŽ Π·Π°Π΄Π°Π½ΠΈΠΉ с ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ сСмафора

#include <malloc.h>

#include <pthread.h>

#include <semaphore.h>


struct job {

 /* Бсылка Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ элСмСнт связанного списка. */

 struct job* next;


 /* Π”Ρ€ΡƒΠ³ΠΈΠ΅ поля, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ... */

};


/* Бписок ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… Π·Π°Π΄Π°Π½ΠΈΠΉ. */

struct job* job_queue;


/* Π˜ΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор, Π·Π°Ρ‰ΠΈΡ‰Π°ΡŽΡ‰ΠΈΠΉ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. */

pthread_mutex_t job_queue_mutex =

 PTHREAD_MUTEX_INITIALIZER;


/* Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€, ΠΏΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ число Π³Π°Π΄Π°Π½ΠΈΠΉ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. */

sem_t job_queue_count;


/* ΠΠ°Ρ‡Π°Π»ΡŒΠ½Π°Ρ инициализация ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. */

void initialize_job_queue() {

 /* Π’Π½Π°Ρ‡Π°Π»Π΅ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ пуста. */

 job_queue = NULL;

 /* УстанавливаСм Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика сСмафора

    Ρ€Π°Π²Π½Ρ‹ΠΌ 0. */

 sem_init(&job_queue_count, 0, 0);

}


/* ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π·Π°Π΄Π°Π½ΠΈΠΉ Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π½Π΅ опустССт. */

void* thread_function(void* arg) {

 while (1) {

  struct job* next_job;

  /* ДоТидаСмся готовности сСмафора. Если Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ большС

     нуля, Π·Π½Π°Ρ‡ΠΈΡ‚, ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π½Π΅ пуста; ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅ΠΌ счСтчик Π½Π° 1.

     Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС опСрация блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ°

     Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ Π½Π΅ появится Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅. */

  sem_wait(&job_queue_count);

  /* Π—Π°Ρ…Π²Π°Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора, Π·Π°Ρ‰ΠΈΡ‰Π°ΡŽΡ‰Π΅Π³ΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. */

  pthread_mutex_lock(&job_queue_mutex);

  /* ΠœΡ‹ ΡƒΠΆΠ΅ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π½Π΅ пуста, поэтому Π±Π΅Π· лишнСй

     ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅. */

  next_job = job_queue;

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

  job_queue = job_queue->next;

  /* освобоТдаСм ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π° с

     ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒΡŽ ΠΎΠΊΠΎΠ½Ρ‡Π΅Π½Π°. */

  pthread_mutex_unlock(&job_queue_mutex);

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

  process_job(next_job);

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

  free(next_job);

 }

 return NULL;

}


/* Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ задания Π² Π½Π°Ρ‡Π°Π»ΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. */

void enqueue_job(/* ΠŸΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…... */) {

 struct job* new_job;


 /* Π’Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠ΅ памяти для Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° задания. */

 new_job = (struct job*)malloc(sizeof(struct job));

 /* Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠΎΠ»Π΅ΠΉ структуры JOB... */


 /* Π—Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ

    ΠΊ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. */

 pthread_mutex_lock(&job_queue_mutex);

 /* ΠŸΠΎΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅ Π² Π½Π°Ρ‡Π°Π»ΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. */

 new_job->next = job_queue;

 job_queue = new_job;


 /* УстанавливаСм сСмафор, сообщая ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ появилось

    Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅. Если Π΅ΡΡ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊΠΈ, Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ

    сСмафора, ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π½ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ ΠΈ

    ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π·Π°Π΄Π°Π½ΠΈΠ΅. */

 sem_post(&job_queue_count);


 /* ОсвобоТдаСм ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор. */

 pthread_mutex_unlock(&job_queue_mutex);

}

ΠŸΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΈΠ· ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ доТидаСтся сСмафора. Если счСтчик сСмафора Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ, Ρ‚.Π΅. ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ пуста, ΠΏΠΎΡ‚ΠΎΠΊ блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ Π½Π΅ появится Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΈ счСтчик Π½Π΅ станСт ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ.

Ѐункция enqueue_job() добавляСт Π½ΠΎΠ²ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. Подобно ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΎΠ½Π° Π·Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ сСмафор, ΠΏΠ΅Ρ€Π΅Π΄ Ρ‚Π΅ΠΌ ΠΊΠ°ΠΊ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒΡΡ ΠΊ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. ПослС добавлСния задания функция enqueue_job() устанавливаСт сСмафор, сообщая ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π·Π°Π΄Π°Π½ΠΈΠ΅ доступно. Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅, ΠΏΠΎΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π² листингС 4.12, ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‚ΡΡ: Ссли задания Π½Π΅ ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‚ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, всС ΠΏΠΎΡ‚ΠΎΠΊΠΈ пСрСводятся Π² Ρ€Π΅ΠΆΠΈΠΌ блокирования Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ sem_wait().

4.4.6. Π‘ΠΈΠ³Π½Π°Π»ΡŒΠ½Ρ‹Π΅ (условныС) ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅

ΠœΡ‹ ΡƒΠ·Π½Π°Π»ΠΈ, ΠΊΠ°ΠΊ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ доступа со стороны Π΄Π²ΡƒΡ… ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² ΠΈ ΠΊΠ°ΠΊ посрСдством ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ³ΠΎ сСмафора Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ счСтчик ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΉ, доступный нСскольким ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌ. Бигнальная пСрСмСнная (называСмая Ρ‚Π°ΠΊΠΆΠ΅ условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ) β€” это Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ элСмСнт синхронизации Π² Linux. Благодаря Π΅ΠΌΡƒ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ слоТныС условия выполнСния ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ².

ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, трСбуСтся Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая Π²Ρ…ΠΎΠ΄ΠΈΡ‚ Π² бСсконСчный Ρ†ΠΈΠΊΠ», выполняя Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΊΠ°ΠΊΠΈΠ΅-Ρ‚ΠΎ дСйствия. Но Ρ€Π°Π±ΠΎΡ‚Π° Ρ†ΠΈΠΊΠ»Π° Π΄ΠΎΠ»ΠΆΠ½Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Ρ„Π»Π°Π³ΠΎΠΌ: дСйствиС выполняСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ установлСн.

Π’ листингС 4.13 ΠΏΠΎΠΊΠ°Π·Π°Π½ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. На ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΈ Ρ†ΠΈΠΊΠ»Π° потоковая функция провСряСт, установлСн Π»ΠΈ Ρ„Π»Π°Π³. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΊ Ρ„Π»Π°Π³Ρƒ обращаСтся сразу нСсколько ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΎΠ½ защищаСтся ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΌ сСмафором. Подобная рСализация являСтся ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ, Π½ΠΎ ΠΎΠ½Π° нСэффСктивна. Если Ρ„Π»Π°Π³ Π½Π΅ установлСн, потоковая функция Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΏΡƒΡΡ‚ΡƒΡŽ Ρ‚Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ рСсурсы процСссора, занимаясь Π±Π΅ΡΡ†Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌΠΈ Ρ„Π»Π°Π³Π°, Π° Ρ‚Π°ΠΊΠΆΠ΅ захватывая ΠΈ освобоТдая сСмафор. На самом Π΄Π΅Π»Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΊΠ°ΠΊ-Ρ‚ΠΎ пСрСвСсти Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π² Π½Π΅Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ Ρ€Π΅ΠΆΠΈΠΌ, ΠΏΠΎΠΊΠ° ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π½Π΅ установит этот Ρ„Π»Π°Π³.

Листинг 4.15. (spin-condvar.c) ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ°Ρ рСализация сигнальной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ

#include <pthread.h>


int thread_flag;

pthread_mutex_t thread_flag_mutex;


void initialize_flag() {

 pthread_mutex_init(&thread_flag_mutex, NULL);

 thread_flag = 0;

}


/* Если Ρ„Π»Π°Π³ установлСн, ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ вызываСтся функция do_work().

   Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Ρ†ΠΈΠΊΠ» Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π²Ρ…ΠΎΠ»ΠΎΡΡ‚ΡƒΡŽ. */

void* thread_function(void* thread_arg) {

 while (1) {

  int flag_is_set;

  /* Π—Π°Ρ‰ΠΈΡ‰Π°Π΅ΠΌ Ρ„Π»Π°Π³ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора. */

  pthread_mutex_lock(&thread_flag_mutex);

  flag_is_set = thread_flag;

  pthread_mutex_unlock(&thread_flag_mutex);

  if (flag_is_set)

   do_work();

  /* Если Ρ„Π»Π°Π³ Π½Π΅ установлСн, Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ. ΠŸΡ€ΠΎΡΡ‚ΠΎ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ

     Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΡƒΡŽ ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΡŽ Ρ†ΠΈΠΊΠ»Π°. */

 }

 return NULL;

}


/* Π—Π°Π΄Π°Π΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ„Π»Π°Π³Π° Ρ€Π°Π²Π½Ρ‹ΠΌ FLAG_VALUE. */

void set_thread_flag(int flag_value) {

 /* Π—Π°Ρ‰ΠΈΡ‰Π°Π΅ΠΌ Ρ„Π»Π°Π³ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора. */

 pthread_mutex_lock(&thread_flag_mutex);

 thread_flag = flag_value;

 pthread_mutex_unlock(&thread_flag_mutex);

}

Бигнальная пСрСмСнная позволяСт ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ, ΠΏΡ€ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π»ΠΈΠ±ΠΎ выполняСтся, Π»ΠΈΠ±ΠΎ блокируСтся. Как ΠΈ Π² случаС сСмафора, ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ ΡΠΈΠ³Π½Π°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ. ΠŸΠΎΡ‚ΠΎΠΊ A, находящийся Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ оТидания, блокируСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π΄Ρ€ΡƒΠ³ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ. Π‘, Π½Π΅ просигнализируСт ΠΎΠ± ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ состояния этой ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Бигнальная пСрСмСнная Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ счСтчика, Ρ‡Ρ‚ΠΎ ΠΎΡ‚Π»ΠΈΡ‡Π°Π΅Ρ‚ Π΅Π΅ ΠΎΡ‚ сСмафора. ΠŸΠΎΡ‚ΠΎΠΊ А Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² состояниС оТидания Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΏΠΎΡ‚ΠΎΠΊ Π‘ ΠΏΠΎΡˆΠ»Π΅Ρ‚ сигнал. Если сигнал Π±ΡƒΠ΄Π΅Ρ‚ послал Ρ€Π°Π½ΡŒΡˆΠ΅, ΠΎΠ½ окаТСтся потСрянным ΠΈ ΠΏΠΎΡ‚ΠΎΠΊ А заблокируСтся, ΠΏΠΎΠΊΠ° ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΏΠΎΡ‚ΠΎΠΊ Π½Π΅ ΠΏΠΎΡˆΠ»Π΅Ρ‚ сигнал Π΅Ρ‰Π΅ Ρ€Π°Π·.

Π’ΠΎΡ‚ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π±ΠΎΠ»Π΅Π΅ эффСктивной.

β–  Π€ΡƒΠ½ΠΊΡ†ΠΈΡ thread_function() Π² Ρ†ΠΈΠΊΠ»Π΅ провСряСт Ρ„Π»Π°Π³. Если ΠΎΠ½ Π½Π΅ установлСн, ΠΏΠΎΡ‚ΠΎΠΊ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² Ρ€Π΅ΠΆΠΈΠΌ оТидания сигнальной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ.

β–  Π€ΡƒΠ½ΠΊΡ†ΠΈΡ set_thread_flag() устанавливаСт Ρ„Π»Π°Π³ ΠΈ сигнализируСт ΠΎΠ± ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Если функция thread_function() Π±Ρ‹Π»Π° Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π° Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ сигнала, ΠΎΠ½Π° разблокируСтся ΠΈ снова провСряСт Ρ„Π»Π°Π³.

Но сущСствуСт ΠΎΠ΄Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°: Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π³ΠΎΠ½ΠΊΠ° ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ„Π»Π°Π³Π° ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ сигнализирования ΠΈΠ»ΠΈ оТидания сигнала. ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ функция thread_function() провСряСт Ρ„Π»Π°Π³ ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΎΠ½ Π½Π΅ установлСн. Π’ этот ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ Linux ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΈ Π°ΠΊΡ‚ΠΈΠ²ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π³Π»Π°Π²Π½ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ. По ΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ ΠΎΠ±ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΡΡ‚Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΊΠ°ΠΊ Ρ€Π°Π· находится Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ set_thread_flag(). Она устанавливаСт Ρ„Π»Π°Π³ ΠΈ сигнализируСт ΠΎΠ± ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ условной ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ. Но ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π½Π΅Ρ‚ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰Π΅Π³ΠΎ получСния этого сигнала (вспомнитС, Ρ‡Ρ‚ΠΎ функция thread_function() Π±Ρ‹Π»Π° ΠΏΡ€Π΅Ρ€Π²Π°Π½Π° ΠΏΠ΅Ρ€Π΅Π΄ Ρ‚Π΅ΠΌ, ΠΊΠ°ΠΊ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ Π² Ρ€Π΅ΠΆΠΈΠΌ оТидания), сигнал окаТСтся потСрян. Когда Linux вновь Π°ΠΊΡ‚ΠΈΠ²ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, ΠΎΠ½ Π½Π°Ρ‡Π½Π΅Ρ‚ ΠΆΠ΄Π°Ρ‚ΡŒ сигнал, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½ΠΈΠΊΠΎΠ³Π΄Π° большС Π½Π΅ ΠΏΡ€ΠΈΠ΄Π΅Ρ‚.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π·Π°Ρ…Π²Π°Ρ‚ΠΈΡ‚ΡŒ ΠΈ Ρ„Π»Π°Π³, ΠΈ ΡΠΈΠ³Π½Π°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π³ΠΎ сСмафора. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, Π² Linux это прСдусмотрСно. Π›ΡŽΠ±Π°Ρ сигнальная пСрСмСнная Π΄ΠΎΠ»ΠΆΠ½Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ совмСстно с ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΌ сСмафором для прСдотвращСния состояния Π³ΠΎΠ½ΠΊΠΈ. Наша потоковая функция Π΄ΠΎΠ»ΠΆΠ½Π° ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠΌΡƒ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡƒ: