Добавил:
jetu
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:T3
.c/*
* Выполнил: —, 93—
* Задание: 3 Поставщик – Потребитель
* Дата выполнения: 17 марта 2023 г.
* Версия: 0.1
*
* Скрипт для компиляции и запуска программы:
* cc T3.c -o T3
* ./T3
*/
// ------------------------------------------- //
/*
* Общее описание программы:
* Создаются потоки поставщика и потребителя, которые
* циклически изменяют общую переменную с использованием
* механизмов семафоров или условных переменных.
*
* Введите "s" в консоль для использования семафора
* или что-то другое для использования условных переменных.
*
* Выводимые сообщения в консоли содержат в себе информацию
* о типе действия, новом значении в буфере, времени начала
* и окончания выполнения задачи.
*/
// ------------------------------------------- //
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#define CONSUME_SLEEP_TIME 3
#define SUPPLY_SLEEP_TIME 1
#define BUFFER_LIMIT 3
#define SEMAPHORE 1
#define CONDITIONAL_VARIABLE 2
// Вариант задания
int type;
// Время запуска программы
double initial_time = 0;
// Синхронизирующие структуры
sem_t semaphore;
pthread_cond_t supplier_cond;
pthread_cond_t consumer_cond;
pthread_mutex_t mutex;
// Общая переменная
int buffer = 0;
// Возвращает время в секундах с момента initial_time.
double get_time() {
struct timeval t;
gettimeofday(&t, NULL);
return (double) t.tv_sec + (double) t.tv_usec / 1000000 - initial_time;
}
// Поток потребителя
void *consumer_routine(void *args) {
double t0;
double t1;
int b;
while (1) {
if (type == SEMAPHORE) {
if (buffer > 0) {
// Блокировка семафора или ожидание, пока он освободиться потребителем
sem_wait(&semaphore);
// Критическая секция. Замеры времени и изменение значения в буфере
t0 = get_time();
b = --buffer;
t1 = get_time();
// Освобождение семафора
sem_post(&semaphore);
// Вывод значения в буфере и времени начала и окончания задачи
printf("Consume (%d): %f → %f\n", b, t0, t1);
}
}
if (type == CONDITIONAL_VARIABLE) {
// Захват мьютекса
pthread_mutex_lock(&mutex);
// Если буфер пуст, освобождение мьютекса и ожидание завершения задачи поставщиком,
// которая просигнализирует об увеличении значения в буфере
if (buffer == 0) pthread_cond_wait(&consumer_cond, &mutex);
// Критическая секция. Замеры времени и изменение значения в буфере
t0 = get_time();
b = --buffer;
t1 = get_time();
// Сигнализирование об уменьшении значения в буфере
pthread_cond_signal(&supplier_cond);
// Освобождение мьютекса
pthread_mutex_unlock(&mutex);
// Вывод значения в буфере и времени начала и окончания задачи
printf("Consume (%d): %f → %f\n", b, t0, t1);
}
sleep(CONSUME_SLEEP_TIME);
}
}
// Поток поставщика
void *supplier_routine(void *args) {
double t0;
double t1;
int b;
while (1) {
if (type == SEMAPHORE) {
if (buffer < BUFFER_LIMIT) {
// Блокировка семафора или ожидание, пока он освободиться потребителем
sem_wait(&semaphore);
// Критическая секция. Замеры времени и изменение значения в буфере
t0 = get_time();
b = ++buffer;
t1 = get_time();
// Освобождение семафора
sem_post(&semaphore);
// Вывод значения в буфере и времени начала и окончания задачи
printf("Supply (%d): %f → %f\n", b, t0, t1);
}
}
if (type == CONDITIONAL_VARIABLE) {
// Захват мьютекса
pthread_mutex_lock(&mutex);
// Если буфер полон, освобождение мьютекса и ожидание завершения задачи потребителем,
// которая просигнализирует об уменьшении значения в буфере
if (buffer == BUFFER_LIMIT) pthread_cond_wait(&supplier_cond, &mutex);
// Критическая секция. Замеры времени и изменение значения в буфере
t0 = get_time();
b = ++buffer;
t1 = get_time();
// Сигнализирование об увеличении значения в буфере
pthread_cond_signal(&consumer_cond);
// Освобождение мьютекса
pthread_mutex_unlock(&mutex);
// Вывод значения в буфере и времени начала и окончания задачи
printf("Supply (%d): %f → %f\n", b, t0, t1);
}
sleep(SUPPLY_SLEEP_TIME);
}
}
int main(int argc, char *argv[]) {
// Выбор варианта задания
type = getchar() == 's' ? SEMAPHORE : CONDITIONAL_VARIABLE;
// Установка времени начала отсчёта
initial_time = get_time();
// Инициализация синхронизирующих структур
if (type == SEMAPHORE) {
printf("Semaphore\n");
sem_init(&semaphore, 0, 1);
}
if (type == CONDITIONAL_VARIABLE) {
printf("Conditional variable\n");
pthread_cond_init(&supplier_cond, NULL);
pthread_cond_init(&consumer_cond, NULL);
pthread_mutex_init(&mutex, NULL);
}
// Создание и запуск потоков
pthread_t consumer_thread;
pthread_t supplier_thread;
pthread_create(&consumer_thread, NULL, &consumer_routine, NULL);
pthread_create(&supplier_thread, NULL, &supplier_routine, NULL);
pthread_join(consumer_thread, NULL);
pthread_join(supplier_thread, NULL);
return EXIT_SUCCESS;
}
// ----------------------------------------//
/*
s
Semaphore
Supply (1): 0.000794 → 0.000794
Supply (2): 1.000891 → 1.000891
Supply (3): 2.001403 → 2.001404
Consume (2): 3.000295 → 3.000295
Supply (3): 3.001480 → 3.001480
Consume (2): 6.000719 → 6.000720
Supply (3): 6.002536 → 6.002537
Consume (2): 9.001122 → 9.001122
Supply (3): 9.003046 → 9.003046
Consume (2): 12.001577 → 12.001577
Supply (3): 12.004344 → 12.004345
Consume (2): 15.001982 → 15.001983
Supply (3): 15.005773 → 15.005773
Consume (2): 18.002177 → 18.002177
Supply (3): 18.006891 → 18.006892
*/
/*
c
Conditional variable
Supply (1): 0.000159 → 0.000160
Consume (0): 0.000207 → 0.000207
Supply (1): 1.000362 → 1.000362
Supply (2): 2.000901 → 2.000901
Consume (1): 3.000575 → 3.000575
Supply (2): 3.001011 → 3.001011
Supply (3): 4.001823 → 4.001823
Consume (2): 6.009274 → 6.009274
Supply (3): 6.009328 → 6.009328
Consume (2): 9.011266 → 9.011267
Supply (3): 9.011464 → 9.011464
Consume (2): 12.011576 → 12.011577
Supply (3): 12.011617 → 12.011617
Consume (2): 15.012196 → 15.012196
Supply (3): 15.012291 → 15.012291
Consume (2): 18.012841 → 18.012841
Supply (3): 18.012914 → 18.012914
*/