Пример готовой курсовой работы по предмету: Программирование
Содержание
Для понимания значения синхронизации рассмотрим простой пример. Предположим, что два по-
тока используют одну и ту же глобальную переменную.
Поток А Поток В
x = common_variable ; y = common_variable ;
x++ ; y— ;
common_variable = x ; common_variable = y ;
В данном случае результат будет зависеть от того, в какой последовательности будет происходить
выполнение двух процессов. Данная ситуация называется состязанием. Состязания обычно трудно
обнаружить, потому что они появляются время от времени без какой-либо закономерности.
Мьютексы
Мьютекс (mutex) – это сокращение от «взаимное исключение» (mutual exlusion).
Мьютексы – это
один из основных способов реализации синхронизации потоков в ОС Linux.
Мьютекс действует как блокировка, защищающая доступ к разделенной структуре данных. Ос-
новная идея работы мьютексов заключается в том, что в определенный момент времени захватить
мьютекс может только один единственный поток. Никакие потоки не могут захватить мьютекс до
тех пор, пока владеющий поток не освободит данный мьютекс.
Очень часто потоки, использующие мьютексы, выполняют действия над глобальными перемен-
ными. Использование мьютексов – безопасный способ изменения глобальной переменной не-
сколькими потоками, гарантирующий, что конечное значение будет таким же, как и в случае, если
бы эти действия выполнялись одним потоком.
Лабораторная работа № 3 по дисциплине «Операционные системы» 2
Функции для работы с мьютексами
Функция int pthread_mutex_init( pthread_mutex_t *mutex,
const pthread_mutexattr_t *mutexattr);
Описание
Создание и инициализация нового мьютекса mutex и установка его атрибутов в
соответствие с атрибутами мьютекса mutexattr. При создании мьютекс разбло-
кирован. Вместо указателя на атрибуты мьютекса допускается передача указателя
NULL, что означает атрибуты по умолчанию.
Функция int pthread_mutex_destroy(pthread_mutex_t *mutex);
Описание Уничтожение мьютекса.
Функция int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
Описание Создание и уничтожение атрибутов мьютекса.
Функция int pthread_mutex_lock(pthread_mutex_t *mutex);
Описание Захват мьютекса. Если данный мьютекс уже захвачен другим потоком, этот вызов
заблокирует вызывающий поток до тех пор, пока мьютекс не будет освобожден.
Функция int pthread_mutex_trylock(pthread_mutex_t *mutex);
Описание
Попытка захватить мьютекс. Однако если мьютекс уже захвачен другим потоком,
этот вызов не будет блокировать вызывающий поток, а вернет управление не-
медленно. Эта функция может быть полезна для предотвращения взаимоблокиро-
вок.
Функция int pthread_mutex_unlock(pthread_mutex_t *mutex);
Описание
Освобождение мьютекса, если его владелец – вызывающий поток. Вызов этой
функции необходим, если поток закончил работу с защищенными данными и дру-
гие потоки ожидают освобождения мьютекса. Если мьютекс уже освобожден, или
владельцем его является другой поток, то функция возвращает ошибку.
Примеры использования мьютексов
Пример
1. Программа без мьютексов.
#include
#include
int x=1;
void* compute_thread(void * argument)
{
printf("X value in thread before sleep = %d\n",x);
printf("X value in thread is incremented by 1 before sleep\n");
x++;
sleep(2);
printf("X value in thread after sleep = %d\n",x);
return;
}
Лабораторная работа № 3 по дисциплине «Операционные системы» 3
main( )
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr;);
pthread_create(&tid;, &attr;, compute_thread,(void *)NULL);
sleep(1);
x++;
printf("Main thread increments X, after that X value is %d\n",x);
pthread_join(tid,NULL);
exit(0);
}
Пример
2. Предыдущий пример, но с использованием мьютекса.
#include
#include
int x=1;
/* This is the lock for thread synchronization */
pthread_mutex_t my_sync;
void* compute_thread(void * argument)
{
printf("X value in thread before sleep = %d\n",x);
printf("X value in thread is incremented by 1 before sleep\n");
pthread_mutex_lock(&my;_sync);
x++;
sleep(2);
printf("X value in thread after sleep = %d\n",x);
pthread_mutex_unlock(&my;_sync);
return;
}
main( )
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr;);
/* Initialize the mutex (default attributes) */
pthread_mutex_init (&my;_sync,NULL);
pthread_create(&tid;, &attr;, compute_thread,(void *)NULL);
sleep(1);
pthread_mutex_lock(&my;_sync);
x++;
printf("Main thread increments X, after that X value is %d\n",x);
Лабораторная работа № 3 по дисциплине «Операционные системы» 4
pthread_mutex_unlock(&my;_sync);
pthread_join(tid,NULL);
exit(0);
}
Условные переменные
Условные переменные предлагают еще один способ синхронизации потоков. В то время как
мьютексы реализуют синхронизацию путем контроля доступа со стороны потоков к данным,
условные переменные позволяют потокам синхронизироваться, исходя из значения переменной.
Без условных переменных программисту пришлось бы непрерывно опрашивать переменную (воз-
можно в критической секции – части программы, где могут происходить состязания) до тех пор,
пока ее значение не станет равным ожидаемому. Это может потребовать много ресурсов, прежде
всего, процессорного времени. Условные переменные позволяют добиться той же цели без опроса.
Условная переменная всегда используется в паре с мьютексом.
Типичная последовательность для использования условной переменной:
• создание и инициализация условной переменной
• создание и инициализация ассоциированного мьютекса
• определение предиката (переменной, значение которой должно быть проверено)
• захват мьютекса
• исполнение потока доходит до точки, где ему нужно ждать выполнения какого-либо события
(например, установки предиката в определенное значение)
• поток ждет условную переменную, выполняя следующие действия
o освобождение мьютекса
o ожидание изменения предиката с использованием условной переменной
• другой поток производит вычисления, меняет значение предиката, сообщает об этом ждуще-
му потоку, производя следующие действия
o захват мьютекса
o изменение предиката
o сигнализация через условную переменную
o освобождение мьютекса
Функции для работы с условными переменными
Функция int pthread_cond_init(pthread_cond_t *cond,
pthread_condattr_t *cond_attr);
Описание Создание и инициализация новой условной переменной. Идентификатор созданной
условной переменной возвращается через параметр cond.
Функция int pthread_cond_destroy(pthread_cond_t *cond);
Описание Уничтожение условной переменной cond, освобождение выделенной ранее памяти.
Функция int pthread_cond_wait(pthread_cond_t *cond,
pthread_mutex_t *mutex);
Описание Блокировка вызывающего потока до вызова из другого потока функции
Лабораторная работа № 3 по дисциплине «Операционные системы» 5
pthread_cond_signal или pthread_cond_broadcast. Эта функция долж-
на вызываться после захвата мьютекса; она освобождает мьютекс на все время
ожидания.
Функция int pthread_cond_signal(pthread_cond_t *cond);
Описание
Эта функция будит другой поток (неизвестно какой, если их несколько), который
усыплен на условной переменной. Эта функция должна вызываться после захвата
мьютекса.
Функция int pthread_cond_broadcast(pthread_cond_t *cond);
Описание Эта функция используется взамен pthread_cond_signal, если нужно разбу-
дить сразу все усыпленные потоки.
Пример
3. Использование условной переменной.
#include
#include
void* compute_thread (void*);
pthread_mutex_t my_sync;
pthread_cond_t rx;
int thread_done = 0;
int x=1;
main( )
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init (&attr;);
pthread_mutex_init (&my;_sync, NULL);
pthread_cond_init (℞, NULL);
pthread_create(&tid;, &attr;, compute_thread, (void *)NULL);
pthread_mutex_lock(&my;_sync);
while (!thread_done) pthread_cond_wait(℞, &my;_sync);
x++;
printf("Main thread increments X, after that X value is %d\n",x);
pthread_mutex_unlock(&my;_sync);
exit(0);
}
void* compute_thread(void* dummy)
{
printf("X value in thread before sleep = %d\n",x);
printf("X value in thread is incremented by 1 before sleep\n");
pthread_mutex_lock (&my;_sync);
x++;
sleep(2);
Лабораторная работа № 3 по дисциплине «Операционные системы» 6
printf("X value in thread after sleep = %d\n",x);
thread_done = 1;
pthread_cond_signal (℞);
pthread_mutex_unlock (&my;_sync);
return;
Выдержка из текста
Общие сведения
При выполнении нескольких потоков довольно часто требуется их синхронизировать в таких си-
туациях, как осуществление доступа к общим ресурсам. Одно из основных преимуществ исполь-
зования потоков – это легкость использования средств синхронизации. В данной лабораторной
работе мы рассмотрим следующие средства синхронизации, используемые в ОС Linux:
• блокировки взаимного исключения (мьютексы),
• условные переменные.
Список использованной литературы
Методичка.