You are on page 1of 7

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего


профессионального образования

«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет автоматики и вычислительной техники

Кафедра ВТ

Отчет по лабораторной работе №3


по дисциплине «Операционные системы»

Знакомство с подсистемой управления потоками в


операционной системе Unix

Выполнила:
студентка гр. 8В51
Юнусова М.Р.

Проверил:
доцент каф. ВТ
Замятин А.В.

Томск 2008
Цель работы
Ознакомиться с подсистемой управления потоками в операционной системе Unix и
основными программными средствами для создания, управления и удаления потоков.

Задание на лабораторную работу


Изучить особенности работы с утилитой Make при создании проекта на языке С (С++) в ОС
Unix, а также получить практические навыки использования утилиты GNU Make при
создании и сборке проекта.

Исходные тексты созданных программ с пояснениями,


иллюстрирующими ход выполнения работы.
1. Синхронизация потоков с использованием мьютекса
В данной программе присутствуют два потока. В первом потоке происходит генерация
случайных чисел и запись этих чисел в файл. Во втором потоке числа считываются из файла и
выводятся на экран, подсчитывается и выводится сумма этих чисел.
#include <pthread.h>
#include <fstream.h>
#include <iostream.h>
#include <time.h>

ofstream output;
ifstream input;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
const char* filename = "output.txt";
const int n = 5;

void* Gen(void* arg);


void* Sum(void* arg);

int main(){
srand(time(NULL));

pthread_t GenThread, SumThread;


pthread_create(&GenThread, NULL, Gen, NULL);
pthread_create(&SumThread, NULL, Sum, NULL);

pthread_join(GenThread, NULL);
pthread_join(SumThread, NULL);

pthread_mutex_destroy(&mutex);
}
void* Gen (void* arg){
for (int i = 0; i < n; i++){
pthread_mutex_lock(&mutex);
output.open(filename);
output<<(rand() % 100)<<" ";
output.close();
pthread_mutex_unlock(&mutex);
sleep(1);
}
}

void* Sum (void* arg){


int a, s=0;
for (int i = 0; i < n; i++){
pthread_mutex_lock(&mutex);
input.open(filename);
input>>a;
cout<<a<<" ";
s += a;
input.close();
pthread_mutex_unlock(&mutex);
sleep(1);
}
cout<<"\nsum = "<<s<<'\n';
}

Вывод программы на экран:


13 77 33 49 16
sum = 188

В приведенном примере функция использует мьютекс, чтобы гарантировать, что данные


записываются в файл и считываются из файла атомарно.

2. Синхронизация потоков с использованием семафора


Описанную выше программу можно реализовать с использованием для синхронизации
потоков семафора. При этом исходный текст программы изменяется незначительно.
#include <semaphore.h>
#include <pthread.h>
#include <fstream.h>
#include <iostream.h>
#include <time.h>

ofstream output;
ifstream input;
sem_t semaphore;
const char* filename = "output.txt";
const int n = 5;

void* Gen(void* arg);


void* Sum(void* arg);

int main(){
srand(time(NULL));

sem_init(&semaphore, 0, 1);

pthread_t GenThread, SumThread;


pthread_create(&GenThread, NULL, Gen, NULL);
pthread_create(&SumThread, NULL, Sum, NULL);

pthread_join(GenThread, NULL);
pthread_join(SumThread, NULL);

sem_destroy(&semaphore);
}

void* Gen (void* arg){


for (int i = 0; i < n; i++){
sem_wait(&semaphore);
output.open(filename);
output<<(rand() % 100)<<" ";
output.close();
sem_post(&semaphore);
sleep(1);
}
}

void* Sum (void* arg){


int a, s=0;
for (int i = 0; i < n; i++){
sem_wait(&semaphore);
input.open(filename);
input>>a;
cout<<a<<" ";
s += a;
input.close();
sem_post(&semaphore);
sleep(1);
}
cout<<"\nsum = "<<s<<'\n';
}

Вывод программы:
23 58 70 98 71
sum = 320

Вывод данной программы аналогичен выводу программы, приведенной в предыдущем


пункте. Таким образом, способ использования семафора сходен со способом использования
мьютекса. Отличительной чертой использования семафора является возможность
одновременной работы не одного, а нескольких потоков, но при этом их число все же
остается ограниченным и задается программистом при инициализации семаформа.

3. Синхронизация потоков с использованием условной переменной


В данной программе присутствуют два потока. В первом потоке происходит сложение
разделяемой переменной со случайными числами. Во втором потоке происходит деление этой
переменной на 2, но лишь в том случае, если ее значение в данный момент времени является
четным числом.
#include <pthread.h>
#include <iostream.h>
#include <time.h>
#include <stdlib.h>

void* Addition(void* arg);


void* Division(void* arg);

int num = 1, add = 0;


pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t pcond = PTHREAD_COND_INITIALIZER;

int main(){
srand(time(NULL));

pthread_t AdditionThread, DivisionThread;


pthread_create(&AdditionThread, NULL, Addition, NULL);
pthread_create(&DivisionThread, NULL, Division, NULL);

pthread_join(AdditionThread, NULL);
pthread_cancel(DivisionThread);
pthread_join(DivisionThread, NULL);

pthread_mutex_destroy(&pmutex);
pthread_cond_destroy(&pcond);
}

void* Addition(void* arg){


for (int i = 0; i < 10; i++){
pthread_mutex_lock(&pmutex);
add = rand() % 10 + 1;
cout<<num<<" + "<<add<<" = ";
num += add;
cout<<num<<'\n';
pthread_mutex_unlock(&pmutex);

pthread_mutex_lock(&pmutex);
pthread_cond_signal(&pcond);
pthread_mutex_unlock(&pmutex);
sleep(1);
}
}
void* Division(void* arg){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_mutex_lock(&pmutex);
while (true){
while (num % 2){
pthread_cond_wait(&pcond, &pmutex);
}
cout<<num<<" / 2 = ";
num /= 2;
cout<<num<<'\n';
}
pthread_mutex_unlock(&pmutex);
}

Вывод программы:
1+8=9
9 + 7 = 16
16 / 2 = 8
8/2=4
4/2=2
2/2=1
1 + 9 = 10
10 / 2 = 5
5+1=6
6/2=3
3 + 7 = 10
10 / 2 = 5
5+1=6
6/2=3
3+1=4
4/2=2
2/2=1
1 + 10 = 11
11 + 3 = 14
14 / 2 = 7
7 + 6 = 13

Условная переменная позволяет второму потоку ожидать выполнения условия четности


разделяемой перменной.

Выводы
В ходе выполнения лабораторной работы мною были изучены средства для создания,
удаления и синхронизации потоков. Синхронизация потоков может осуществляться
посредством семафоров, мьютексов и условных переменных. Мьютекс можно определить как
объект синхронизации, который устанавливается в особое сигнальное состояние, когда не
занят каким-либо потоком. В любой момент временем мьютексом может владеть только один
поток. Семафор предназначен для синхронизации потоков по действиям и по данным и в
общем случае способ использования семафора сходен со способом использования мьютексов.
Условная переменная позволяет потокам ожидать выполнения некоторого условия (события),
связанного с разделяемыми данными. Условная переменная всегда используется совместно с
мьютексом.