Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные. Дагаев / Операционные_системы_ЛР_№3_Отчет.docx
Скачиваний:
1
Добавлен:
02.01.2026
Размер:
394.93 Кб
Скачать

Министерство цифрового развития, связи и массовых коммуникаций Российской Федерации

Федеральное государственное бюджетное образовательное учреждение Высшего образования «Санкт-Петербургский государственный университет телекоммуникаций им. Проф. М. А. Бонч-Бруевича» (СПбГУТ)

Факультет Информационных технологий и программной инженерии

Кафедра Программной инженерии

Лабораторная работа №3

По дисциплине: Операционные системы и сети

Выполнил студент:

Яковлев М. А. ИКПИ-32

Принял работу:

Дагаев А. В.

Дата выполнения:

«05» ноября 2025 г.

Санкт-Петербург

2025 г.

Постановка задачи

Необходимо разработать многопоточный алгоритм, моделирующий работу алгоритма «Читатели-Писатели». Программа должна обеспечивать синхронизацию доступа к общему ресурсу (хранилищу данных) между несколькими потоками-читателями и потоками-писателями. Используются семафоры.

Семафор — это специальная переменная или объект в программировании, используемый для контроля доступа к общим (разделяемым) ресурсам, таким как память, файлы или устройства. Он особенно важен при многопоточном и параллельном программировании. Семафор работает как контролёр, разрешая или блокируя доступ к ресурсу, чтобы избежать конфликтов и ошибок при одновременном доступе нескольких потоков.

Перечень функций

В коде используются следующие функции:

  1. TimeStats::addDuration — добавляет значение времени выполнения операции в вектор для статистики.

  2. Класс FastSemaphore:

    • FastSemaphore(long initial) — конструктор, инициализирует счётчик и создаёт событие Windows.

    • ~FastSemaphore() — деструктор, закрывает событие.

    • wait() — пытается атомарно уменьшить счётчик, при его отсутствии ждёт сигнала события.

    • signal() — увеличивает счётчик и пробуждает поток через событие, если требуется.

  3. Функции-потоки с FastSemaphore:

    • writerFastFunc — цикл операций записи с ожиданием и сигналом семафора, измеряет время выполнения.

    • readerFastFunc — цикл операций чтения с аналогичным контролем и замером времени.

  4. Функции-потоки с std::counting_semaphore:

    • writerStdFunc — операция записи с использованием встроенного семафора.

    • readerStdFunc — операция чтения с использованием встроенного семафора.

  5. main — точка входа, где

    • Инициализируются параметры тестов, создаются потоки для обоих видов семафора.

    • Запускаются и дожидаются завершения потоков.

    • Собранные параметры времени сохраняются в CSV-файлы для дальнейшего анализа.

Вся логика построена вокруг синхронизации потоков-писателей и читателей с использованием двух видов семафоров, а также измерения и записи времени для сравнения производительности.

Описание алгоритма

Программа моделирует классическую задачу синхронизации «Читатели-Писатели» с приоритетом писателей. Алгоритм работает следующим образом:

  1. Алгоритм работы данного кода построен на синхронизации потоков с помощью критических секций Windows для безопасного доступа к общему ресурсу — целочисленному хранилищу. Изначально в главной функции инициализируются три критические секции: для защиты операций записи в хранилище, для защиты флага блокировки чтения и для безопасного логирования. Создаются два типа потоков — писатели и читатели, а также отдельный мониторящий поток, который наблюдает за завершением работы всех потоков.

  2. Поток-писатель при каждой итерации пытается войти в критическую секцию записи, сигнализируя о намерении выполнить запись. После захвата критической секции он помечает, что чтение в данный момент запрещено, и ждет, пока все активные читатели завершат свои операции, отслеживая счётчик активных читателей. Затем он выполняет имитацию записи, обновляя общее хранилище, и освобождает блокировки, позволяя другим потокам работать с ресурсом.

  3. Поток-читатель в начале каждой операции ждет, пока не будет снят запрет на чтение, установленный писателями, проверяя специальный флаг внутри критической секции. После того как доступ к чтению разрешен, он увеличивает счетчик активных читателей, читает значение из хранилища и затем уменьшает счетчик. Все операции тесно вынуждены выполнять синхронизированно, чтобы избежать одновременного изменения данных.

  4. Мониторный поток периодически проверяет сколько писателей и читателей выполнили все свои операции и выводит информацию о текущем прогрессе. Как только все потоки завершают работу, монитор сигнализирует о завершении программы.

График

График, построенный на основе полученной статистики.

Рисунок 1. График временных затрат

На графике (рис. 1) представлены временные затраты на работу двух видов семафоров: пользовательского и встроенного (стандартного). Видно, что пользовательский семафор имеет немного меньшую задержку в сравнении со встроенным. Однако эффективность пользовательского семафора начинает превосходить стандартный только при больших объёмах данных.

Демонстрационная таблица 1.

Таблица 2. Описание первых нескольких шагов

Время

Роль

Сообщение

Шаг 1

Писатель 0

обратился к хранилищу...

Шаг 2

Писатель 0

получил доступ к хранилищу.

Шаг 3

Писатель 0

записал в хранилище сообщение 18467 и закончил работу.

Шаг 4

Читатель 0

обратился к хранилищу...

Шаг 5

Читатель 0

получил доступ к хранилищу.

Шаг 6

Писатель 1

обратился к хранилищу...

Шаг 7

Писатель 1

ожидает, пока активные читатели закончат работу с хранилищем.

Шаг 8

Читатель 0

прочитал из хранилища 18467 и закончил работу.

Шаг 9

Писатель 1

получил доступ к хранилищу.

Шаг 9

Писатель 1

записал в хранилище сообщение 18468 и закончил работу.

Рисунок 1. Схема работы первых шагов

В рамках последовательности временных отметок зафиксированы взаимодействия между участниками системы хранения данных. Сначала Писатель 0 обращается к хранилищу и получает доступ, после чего записывает в хранилище сообщение с идентификатором 18467 и завершает работу. Затем Читатель 0 обращается к хранилищу и получает доступ, последующим шагом Писатель 1 обращается к хранилищу и ожидает, пока активные читатели закончат работу. В более поздний момент Читатель 0 читает из хранилища сообщение 18467 и завершает работу. После этого Писатель 1 снова получает доступ к хранилищу, записывает сообщение 18468 и завершает операцию. Общая картина демонстрирует последовательность чтения и записи с синхронизацией между читателями и писателями, включая ожидание завершения текущих операций перед продолжением записи новыми сообщениями.

Демонстрационная таблица 2.

Таблица 2. Описание шагов

Время

Роль

Действие

Сообщение

Шаг 1

Писатель 0

Обратился

Обратился к хранилищу...

Шаг 2

Читатель 0

Обратился

Обратился к хранилищу...

Шаг 3

Писатель 0

Получил

Получил доступ к хранилищу.

Шаг 4

Писатель 1

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 5

Читатель 0

Получил

Получил доступ к хранилищу.

Шаг 6

Читатель 1

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 7

Писатель 0

Записал

Записал в хранилище сообщение 18467 и освободил ресурс.

Шаг 8

Читатель 0

Прочитал

Прочитал из хранилища 18467 и освободил ресурс.

Шаг 9

Писатель 1

Получил

Получил доступ к хранилищу.

Шаг 10

Писатель 2

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 11

Читатель 1

Получил

Получил доступ к хранилищу.

Шаг 12

Писатель 1

Записал

Записал в хранилище сообщение 18468 и освободил ресурс.

Шаг 13

Читатель 1

Прочитал

Прочитал из хранилища 18468 и освободил ресурс.

Шаг 14

Читатель 2

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 15

Писатель 3

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 16

Читатель 2

Получил

Получил доступ к хранилищу.

Шаг 17

Писатель 2

Получил

Получил доступ к хранилищу.

Шаг 18

Читатель 2

Прочитал

Прочитал из хранилища 18468 и освободил ресурс.

Шаг 19

Писатель 2

Записал

Записал в хранилище сообщение 18469 и освободил ресурс.

Шаг 20

Писатель 3

Получил

Получил доступ к хранилищу.

Шаг 21

Читатель 3

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 22

Писатель 3

Записал

Записал в хранилище сообщение 18470 и освободил ресурс.

Шаг 23

Читатель 3

Получил

Получил доступ к хранилищу.

Шаг 24

Читатель 3

Прочитал

Прочитал из хранилища 18470 и освободил ресурс.

Шаг 25

Писатель 4

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 26

Читатель 4

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 27

Писатель 4

Получил

Получил доступ к хранилищу.

Шаг 28

Читатель 4

Получил

Получил доступ к хранилищу.

Шаг 29

Писатель 4

Записал

Записал в хранилище сообщение 18471 и освободил ресурс.

Шаг 30

Читатель 4

Прочитал

Прочитал из хранилища 18471 и освободил ресурс.

Шаг 31

Писатель 5

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 32

Читатель 5

Обратился

Обратился к хранилищу и ожидает доступа.

Шаг 33

Писатель 5

Получил

Получил доступ к хранилищу.

Шаг 34

Читатель 5

Получил

Получил доступ к хранилищу.

Шаг 35

Писатель 5

Записал

Записал в хранилище сообщение 18472 и освободил ресурс.

Шаг 36

Читатель 5

Прочитал

Прочитал из хранилища 18472 и освободил ресурс.

Шаг 1-2: Писатель 0 и читатель 0 одновременно обратились к общему хранилищу, пытаясь получить к нему доступ.

Шаг 3: Писатель 0 получил доступ и стал работать, остальные, включая писателя 1 и читателя 1, продолжают ожидать.

Шаг 4-6: Писатель 1 и читатель 1 обратились к хранилищу и вынуждены ожидать освобождения, так как ресурс занят.

Шаг 7-8: Писатель 0 завершил запись, а читатель 0 прочитал данные, освобождая ресурс.

Шаг 9-13: Писатель 1 получает доступ и выполняет запись, читатель 1 затем получает доступ и читает, оба завершают работу.

Шаг 14-20: Вновь другие потоки (писатель 2, читатель 2, писатель 3) обращаются к хранилищу, часть из них ожидает освобождения ресурса, другие получают доступ, выполняют операции записи или чтения и освобождают доступ.

Шаг 21-36: Аналогично, оставшиеся писатели и читатели (4 и 5) поочередно обращаются, ждут, получают доступ, выполняют операции и завершают работу.

В каждом шаге происходит динамическое чередование состояний "обратился", "ожидает доступа", "получил доступ", "выполнил операцию (записал/прочитал)" и освобождения ресурса для других потоков.