Основы программирования в Linux
Основы программирования в Linux читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
exit(EXIT_FAILURE);
}
Обратите внимание на то, что начальное значение семафора равно 0.
В функции
main
sem_post
printf("Input some text. Enter 'end' to finishn");
while(strncmp("end", work_area, 3) != 0) {
fgets(work_area, WORK_SIZE, stdin);
sem_post(&bin_sem);
}
В новом потоке вы ждете семафор и затем подсчитываете символы ввода:
sem_wait(&bin_sem);
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d charactersn", strlen(work_area)-1);
sem_wait(&bin_sem);
}
Пока семафор установлен, вы ждете ввода с клавиатуры. Когда вы получите некоторый ввод, то освобождаете семафор, разрешив второму потоку сосчитать символы перед тем, как первый поток начнет снова считывать ввод с клавиатуры.
И опять потоки совместно используют один и тот же массив
work_area
sem_wait
Дайте программе отработать:
$ <b>cc -D_REENTRANT thread3.с -о threads -lpthread</b>
$ <b>./thread3</b>
Input some text. Enter 'end', to finish
<b>The Wasp Factory</b>
You input 16 characters
<b>Iain Banks</b>
You input 10 characters
<b>end</b>
Waiting for thread to finish...
Thread joined
В программах с потоками временные ошибки всегда трудно найти, но программа кажется приспособленной и к быстрому вводу текста, и более неспешным паузам.
Как это работает
Когда вы инициализируете семафор, то задаете ему начальное значение, равное 0. Следовательно, когда запускается функция потока, вызов
sem_wait
В потоке
main
sem_post
sem_wait
sem_wait
sem_post
Неочевидные недочеты в разработке, которые заканчиваются в результате неявными ошибками, легко пропустить. Давайте слегка изменим программу на thread3a.c, так чтобы вводимый с клавиатуры текст временами заменялся автоматически формируемым текстом. Замените цикл чтения в
main
printf("Input some text. Enter 'end' to finishn");
while (strncmp("end", work_area, 3) != 0) {
if (strncmp(work_area, "FAST", 4) == 0) {
sem_post(&bin_sem);
strcpy(work_area, "Wheeee...");
} else {
fgets(work_area, WORK_SIZE, stdin);
}
sem_post(&bin_sem);
}
Теперь, если вы введете
FAST
sem_post
work_area
$ <b>cc -D_REENTRANT thread3a.с -о thread3a -lpthread</b>
$ <b>./thread3a</b>
Input some text. Enter 'end' to finish
<b>Excession</b>
You input 9 characters
<b>FAST</b>
You input 7 characters
You input 7 characters
You input 7 characters
<b>end</b>
Waiting for thread to finish...
Thread joined
Проблема этой программы заключается в том, что она рассчитывала на то, что ввод текста из программы продлится так долго, что у другого потока хватит времени для подсчета символов до того, как поток
main
FAST
Wheeee...
Этот пример показывает, как аккуратны вы должны быть с временны́ми условиями в многопоточных программах. Исправить программу можно, применяя дополнительный семафор для того, чтобы заставить поток
main
Синхронизация с помощью мьютексов
Другой способ синхронизации доступа в многопоточных программах — применение мьютексов (сокращение от mutual exclusions — взаимные исключения) или исключающих семафоров, которые разрешают программистам "запирать" объект так, что только один поток может обратиться к нему.
Базовые функции, необходимые для использования мьютексов, очень похожи на функции семафоров. Они объявляются следующим образом: