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

Программа

Текст программы:

#include <iostream>

#include <vector>

#include <thread>

#include <atomic>

#include <chrono>

#include <semaphore>

#include <mutex>

#include <condition_variable>

#include <fstream>

#include <locale>

#include <windows.h>

using namespace std;

using Clock = chrono::steady_clock;

struct TimeStats {

vector<long long> durationsUs;

void addDuration(long long us) { durationsUs.push_back(us); }

};

// Оптимизированный семафор без мьютексов, на атомиках и Windows event

class FastSemaphore {

private:

std::atomic<long> count;

HANDLE event;

public:

explicit FastSemaphore(long initial) : count(initial) {

event = CreateEvent(nullptr, FALSE, FALSE, nullptr);

if (!event) {

throw runtime_error("CreateEvent failed");

}

}

~FastSemaphore() {

CloseHandle(event);

}

void wait() {

while (true) {

long oldCount = count.load(std::memory_order_acquire);

if (oldCount > 0) {

if (count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire))

return; // успешно заняли место

} else {

// Перед ожиданием еще раз проверить, чтобы не пропустить сигнал

if (count.load(std::memory_order_acquire) > 0)

continue;

WaitForSingleObject(event, INFINITE);

}

}

}

void signal() {

long oldCount = count.fetch_add(1, std::memory_order_release);

if (oldCount <= 0) {

SetEvent(event); // пробуждаем поток

}

}

};

struct SharedStorage {

atomic<int> data{0};

};

// Поток-писатель с FastSemaphore

void writerFastFunc(SharedStorage& storage, FastSemaphore& sem, TimeStats& stats, int ops) {

for (int i = 0; i < ops; ++i) {

sem.wait();

auto start = Clock::now();

this_thread::sleep_for(chrono::milliseconds(10));

storage.data.store(rand() % 1000);

auto end = Clock::now();

sem.signal();

long long durUs = chrono::duration_cast<chrono::microseconds>(end - start).count();

stats.addDuration(durUs);

}

}

// Поток-читатель с FastSemaphore

void readerFastFunc(SharedStorage& storage, FastSemaphore& sem, TimeStats& stats, int ops) {

for (int i = 0; i < ops; ++i) {

sem.wait();

auto start = Clock::now();

this_thread::sleep_for(chrono::milliseconds(5));

volatile int val = storage.data.load();

auto end = Clock::now();

sem.signal();

long long durUs = chrono::duration_cast<chrono::microseconds>(end - start).count();

stats.addDuration(durUs);

}

}

// Поток-писатель с std::counting_semaphore

void writerStdFunc(SharedStorage& storage, std::counting_semaphore<1>& sem, TimeStats& stats, int ops) {

for (int i = 0; i < ops; ++i) {

sem.acquire();

auto start = Clock::now();

this_thread::sleep_for(chrono::milliseconds(10));

storage.data.store(rand() % 1000);

auto end = Clock::now();

sem.release();

long long durUs = chrono::duration_cast<chrono::microseconds>(end - start).count();

stats.addDuration(durUs);

}

}

// Поток-читатель с std::counting_semaphore

void readerStdFunc(SharedStorage& storage, std::counting_semaphore<1>& sem, TimeStats& stats, int ops) {

for (int i = 0; i < ops; ++i) {

sem.acquire();

auto start = Clock::now();

this_thread::sleep_for(chrono::milliseconds(5));

volatile int val = storage.data.load();

auto end = Clock::now();

sem.release();

long long durUs = chrono::duration_cast<chrono::microseconds>(end - start).count();

stats.addDuration(durUs);

}

}

int main() {

std::setlocale(LC_ALL, "Russian");

const int writersCount = 8;

const int readersCount = 8;

const int opsPerThread = 1000;

cout << "Запуск теста с FastSemaphore...\n";

SharedStorage storageFast;

FastSemaphore semaphoreFast(1);

vector<thread> threadsFast;

vector<TimeStats> writerStatsFast(writersCount);

vector<TimeStats> readerStatsFast(readersCount);

for (int i = 0; i < writersCount; ++i)

threadsFast.emplace_back(writerFastFunc, ref(storageFast), ref(semaphoreFast), ref(writerStatsFast[i]), opsPerThread);

for (int i = 0; i < readersCount; ++i)

threadsFast.emplace_back(readerFastFunc, ref(storageFast), ref(semaphoreFast), ref(readerStatsFast[i]), opsPerThread);

for (auto& t : threadsFast) t.join();

cout << "Запуск теста с std::counting_semaphore...\n";

SharedStorage storageStd;

std::counting_semaphore<1> semaphoreStd(1);

vector<thread> threadsStd;

vector<TimeStats> writerStatsStd(writersCount);

vector<TimeStats> readerStatsStd(readersCount);

for (int i = 0; i < writersCount; ++i)

threadsStd.emplace_back(writerStdFunc, ref(storageStd), ref(semaphoreStd), ref(writerStatsStd[i]), opsPerThread);

for (int i = 0; i < readersCount; ++i)

threadsStd.emplace_back(readerStdFunc, ref(storageStd), ref(semaphoreStd), ref(readerStatsStd[i]), opsPerThread);

for (auto& t : threadsStd) t.join();

// Сохраняем результаты в файлы для анализа

ofstream outFast("fast_semaphore_times.csv");

outFast << "ThreadType,ThreadID,Operation,DurationUs\n";

for (int i = 0; i < writersCount; ++i)

for (size_t j = 0; j < writerStatsFast[i].durationsUs.size(); ++j)

outFast << "Writer," << i << "," << j << "," << writerStatsFast[i].durationsUs[j] << "\n";

for (int i = 0; i < readersCount; ++i)

for (size_t j = 0; j < readerStatsFast[i].durationsUs.size(); ++j)

outFast << "Reader," << i << "," << j << "," << readerStatsFast[i].durationsUs[j] << "\n";

outFast.close();

ofstream outStd("std_semaphore_times.csv");

outStd << "ThreadType,ThreadID,Operation,DurationUs\n";

for (int i = 0; i < writersCount; ++i)

for (size_t j = 0; j < writerStatsStd[i].durationsUs.size(); ++j)

outStd << "Writer," << i << "," << j << "," << writerStatsStd[i].durationsUs[j] << "\n";

for (int i = 0; i < readersCount; ++i)

for (size_t j = 0; j < readerStatsStd[i].durationsUs.size(); ++j)

outStd << "Reader," << i << "," << j << "," << readerStatsStd[i].durationsUs[j] << "\n";

outStd.close();

cout << "Тесты завершены. Результаты сохранены в fast_semaphore_times.csv и std_semaphore_times.csv\n";

return 0;

}

Выходной файл:

Рисунок 2. Выходной файл

Вывод

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