В общем о семафорах! см.билет№32
Задача о читателях и писателях относится к классическим задачам синхронизации. Она находит свое
практическое применение при организации работы с базами данных, при обслуживании файловых
систем.
Пусть есть две группы процессов. Процесс первой группы просматривает данные, хранящиеся в общей
для всех процессов памяти. Такой процесс будем называть «читатель». Процесс второй группы
записывает новые данные или обновляет ранее записанные данные в общей памяти. Такой процесс
будем называть «писатель».
Процессам-писателям нужен взаимоисключающий доступ к общей памяти. Доступ процессов-читателей как группы также должен быть взаимоисключающим по отношению к любому процессу-писателю.
Наиболее широкое применение на практике нашли два варианта взаимодействия процессов-читателей и
процессов-писателей: взаимодействие с приоритетом «читателей» и взаимодействие с приоритетом
«писателей». В обоих случаях необходимо обеспечить описанное выше взаимное исключение. Различия
между вариантами взаимодействия процессов определяются ограничениями, которые накладываются на
процессы-читатели при появлении процесса-писателя.
В случае приоритета «читателей» действует правило: если хотя бы один «читатель» уже пользуется
ресурсом, то доступ «писателей» к ресурсу закрыт, а вновь приходящие «читатели» беспрепятственно
получают доступ к ресурсу.
Задача «читатели-писатели» с приоритетом «читателей».
Пусть есть несколько процессов-читателей и несколько процессов-писателей. Необходимо
организовать взаимодействие процессов, обеспечив взаимное исключение и приоритет «читателей».
Опишем в самом общем виде процесс-читатель и процесс-писатель:
Process Читатель Process Писатель
{ {
Чтение_данных; Запись_данных;
} }
«Чтение_данных» и «Запись_данных» представляют собой критические секции процессов, для
которых нужно организовать взаимное исключение при доступе к общей памяти. Эту задачу решаем
введением двоичного семафора S:
S=1;
Process Читатель
{
P(S); Чтение_данных; V(S);
}
Process Писатель
{
P(S); Запись_данных; V(S);
}
К сожалению, представленное решение, обеспечив взаимное исключение процессов, не дает
возможность нескольким процессам-читателям одновременно иметь доступ к общему ресурсу.
Учитывая, что первый процесс-читатель, получивший доступ к ресурсу, должен с одной стороны
блокировать доступ к ресурсу процессам-писателям, а с другой - обеспечить беспрепятственный доступ
к ресурсу остальным процессам-читателям, введем переменную Число_читателей и семафор W,
позволяющий организовать взаимное исключение «читателя» и «писателей».
Каждый читатель, получающий доступ к ресурсу, увеличивает значение переменной
Число_читателей на 1, а при завершении работы с ресурсом уменьшает это значение на 1. Последний
«читатель», завершая работу с ресурсом, открывает доступ к ресурсу для писателя.
W=1; Число_читателей=0;
Process Читатель
{
Число_читателей=Число_читателей+1;
Если Число_читателей=1 then P(W);
Чтение_данных;
Число_читателей=Число_читателей-1;
Если Число_читателей=1 then V(W);
}
Process Писатель
{
P(W); Запись_данных; V(W);
}
Представленное выше решение обладает одним недостатком – если два процесса-читателя
одновременно попытаются получить доступ к свободному ресурсу, то каждый из них посчитает себя
первым и в результате один из них будет заблокирован на семафоре W.
Для устранения этого недостатка нужно ввести семафор R, который будет обеспечивать взаимное
исключение процессов-читателей при попытке изменить значение переменной Число_читателей и
установить/снять блокировку доступа процессов-писателей к общему ресурсу.
Окончательное решение будет иметь вид:
W=1; Число_читателей=0; R=1
Process Читатель
{
P(R);
Число_читателей=Число_читателей+1;
Если Число_читателей=1 then P(W);
V(R);
Чтение_данных;
P(R);
Число_читателей=Число_читателей-1;
Если Число_читателей=1 then V(W);
V(R);
}
Process Писатель
{
P(W); Запись_данных; V(W);
}