You are on page 1of 6

Федеральное агентство по образованию

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


образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

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


Направление – Информатика и Вычислительная Техника
Кафедра – Вычислительной техники

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


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

«Многопоточные приложения и синхронизация потоков»

Студент гр. 8В53 ______________________ Афанасьев А.А.


(подпись)

Преподаватель ______________________ Шерстнев В.С.


(подпись)

Томск – 2008
ЦЕЛЬ РАБОТЫ: Ознакомиться с подсистемой управления потоками в
операционной системе Unix и основными программными средствами для
создания, управления и удаления потоков.

ЗАДАНИЕ НА ЛАБОРАТОРНУЮ РАБОТУ: Изучить основные


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

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

В программе имеются 2 функции записывающие в файл «outfile.txt» слова


«first» и «second». При входе в функции осуществляется блокировка с
использованием мьютекса, таким образом при выполнении видим, что
сначала весь цикл отрабатывает первая программа, а затем вторая.

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

#include <pthread.h>
#include <fstream.h>
#include <semaphore.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

pthread_mutex_t lock;
ofstream out;

void* first (void* arg){


pthread_mutex_lock(&lock);

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


out<<"first ";
}
pthread_mutex_unlock(&lock);
return NULL;
}

void* second (void* arg){


pthread_mutex_lock(&lock);
for (int i=0;i<10;i++){
out<<"second ";
}
pthread_mutex_unlock(&lock);
return NULL;
}

int main(){

out.open("outfile.txt");
pthread_mutex_init(&lock, NULL);

pthread_t threadA;
pthread_t threadB;

pthread_create(&threadA,NULL,&first,NULL);
pthread_create(&threadB,NULL,&second,NULL);

pthread_join(threadA,NULL);
pthread_join(threadB,NULL);

pthread_mutex_destroy(&lock);

out.close();

Результат выполнения.

g3u3@linux ~/mut$ g++ mut.cpp –o mut.exe –D _REENTERANT -I/usr/include/nptl -I


/usr/lib/nptl –lpthread
g3u3@linux ~/mut$ ./mut.exe
g3u3@linux ~/mut$ cat outfile.txt
first first first first first first first first first first second second second second second second
second second second second g3u3@linux ~/mut$

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

В программе 2 потока используя 1 и туже функцию, обращаются к 1


переменной. Один поток увеличивает её на 1, другой уменьшает на 1. На
входе в тело функции, функция sem_wait(&sem) блокирует вход для другого
потока. При выполнении убеждаемся, что сначала работает только 1 поток, а
потом только второй.

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

#include <semaphore.h>
#include <pthread.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int count;
sem_t sem;

void* funck(void* arg){

int itt =(int)arg;

sem_wait(&sem);

for (int i=1;i<5;i++){


count=count+itt;
printf("%i",count);
}

sem_post(&sem);
return NULL;

int main(){
sem_init(&sem,0,0);
sem_post(&sem);

pthread_t thread1,thread2;

pthread_create(&thread1,NULL,&funck,(void*)1);
pthread_create(&thread2,NULL,&funck,(void*)-1);

pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

sem_destroy(&sem);

return 0;
}

Результат выполнения.

g3u3@linux ~/mut$ ./sem.exe


12343210g3u3@linux ~/mut$
3.Синхронизация с использованием условных переменных:
В программе 2 потока на основе 2 функций обращаются к общей переменной, один из них
увеличивает переменную на 2, другой уменьшает на 2. Каждый из потоков при выходе
посылает сигнал другому потоку (pthread_cond_signal(&cond)), а сам ожидает
(pthread_cond_wait(&cond, &mutex)). При выполнении видно, что потоки обращаются к
переменной строго по очереди.

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

#include <pthread.h>
#include <fstream.h>
#include <iostream.h>
#include <stdlib.h>

void* add(void *arg);


void* minus(void *arg);

int zn;
pthread_mutex_t mutex;
pthread_cond_t cond;

int main()
{

pthread_mutex_init(&mutex,0);
pthread_cond_init(&cond,0);

pthread_t addT;
pthread_create(&addT,NULL,add,NULL);

pthread_t minusT;
pthread_create(&minusT,NULL,minus,NULL);

pthread_join(addT, NULL);
pthread_cancel(minusT);

pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}

void* add(void *arg)


{

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


{
pthread_mutex_lock(&mutex);
printf("%i",zn);
printf(" ");
zn=zn+2;

pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

}
}

void* minus(void *arg)


{
while (true)
{

pthread_mutex_lock(&mutex);

printf("%i",zn);

printf(" ");

while (zn>0) zn=zn-2;

pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);

}
}

Результат выполнения.

g3u3@linux ~/mut$ ./var.exe


0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 g3u3@linux ~/mut$

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