29. Синхронизация потоков - Примитивы синхронизации.ppt
- Количество слайдов: 54
5. Примитивы синхронизации
5. 1. Примитив синхронизации и блокировка потоков
Определение примитива синхронизации • Примитив синхронизации это программное средство (механизм, инструмент) высокого уровня для решения задач синхронизации потоков. • Программные примитивы синхронизации обычно реализованы как объекты ядра ОС.
Блокировка потоков • Рассмотрим реализацию примитивов синхронизации только для однопроцессорных компьютеров. • При этом предположим, что микропроцессор имеет только одно ядро. • В этом случае атомарность действий можно обеспечить посредством запрещения прерываний. • Чтобы избежать активного ожидания, будем блокировать исполнение потока в случае доступа к примитиву синхронизации, занятому другим потоком.
Очередь потоков • Для этого с каждым примитивом синхронизации свяжем очередь заблокированных потоков, ждущих освобождения этого примитива синхронизации.
Спецификация очереди блокированных потоков class Thread. Queue { Thread *tp; // список потоков public: Thread. Queue(): tp(NULL) { } ~Thread. Queue() {. . . } // здесь нетривиально void enqueue. Thread(Thread& t); bool dequeue. Thread(); };
void Thread. Queue: : enqueue. Thread(Thread& t) { include. Thread. To. List(t); t. suspend. Thread(); } bool Thread. Queue: : dequeue. Thread() { Thread t; if(!tp) return false; else { t = exclude. Thread. From. List(); t. resume. Thread(); return true; } }
5. 2. Примитив синхронизации Lock (замок)
Схема реализации примитива синхронизации Lock class Lock { bool free; Thread. Queue tq; // очередь потоков public: Lock(): free(true) { } ~Lock() {. . . } void acquire() ; // закрываем замок void release(); // открываем замок };
void Lock: : acquire() // закрываем замок { disable. Interrupt(); if (!free) tq. enqueue. Thread(current. Thread()); else free = false; enable. Interrupt(); }
void Lock: : release() // открываем замок { disable. Interrupt(); if (!tq. dequeue. Thread()) free = true; enable. Interrupt(); }
Решение проблемы взаимного исключения для двух потоков при помощи примитива синхронизации Lock • Для этого рассмотрим следующие потоки: Lock lock; void thread_1( ) { before. Critical. Section_1(); lock. acquire(); critical. Section_1(); lock. release(); after. Critical. Section_1(); } void thread_2( ) { before. Critical. Section_2(); lock. acquire(); critical. Section_2(); lock. release(); after. Critical. Section_2(); }
Аналоги примитива Lock в Windows • В операционной системе Windows аналогами примитива синхронизации Lock являются примитивы синхронизации CRITICAL_SECTION и Mutex.
5. 3. Примитив синхронизации Condition (условие)
Схема реализации примитива синхронизации Condition class Condition { bool event; Thread. Queue tq; // очередь потоков public: Condition (): event(false) { } ~Condition () {. . . } void wait(); // ждем выполнения условия void signal(); // сигнализируем о выполнении условия };
// ждем выполнения условия void Condition: : wait() { disable. Interrupt(); if (event) event = false; else tq. enqueue. Thread(current. Thread()); enable. Interrupt(); }
// сигнализируем о выполнении условия void signal() { disable. Interrupt(); if (!tq. dequeue. Thread()) event = true; enable. Interrupt(); }
Решение задачи условной синхронизации для двух потоков при помощи примитива синхронизации Condition • Для этого рассмотрим следующие потоки. Condition c; // начальное состояние несигнальное void thread_1( ) void thread_2( ) { { before. Condition_1(); before. Condition_2(); c. wait(); c. signal(); after. Codition_1(); after. Condition_2(); } }
Решение при помощи примитива синхронизации Condition проблемы взаимного исключения для двух потоков • Для этого рассмотрим следующие потоки: Condition c; // начальное состояние несигнальное c. signal(); // устанавливаем в сигнальное состояние void thread_1( ) void thread_2( ) { { before. Critical. Section_1(); before. Critical. Section_2(); c. wait(); critical. Section_1(); critical. Section_2(); c. signal(); c. signal(); after. Critical. Section_1(); after. Critical. Section_2(); } }
Аналог примитива Condition в Windows • В операционной системе Windows аналогом примитива синхронизации Condition является примитив синхронизации Event.
5. 4. Семафоры Дейкстры
Определение семафора • Семафор – это неотрицательная целочисленная переменная, значение которой может изменяться только при помощи атомарных операций. • Семафор считается свободным, если его значение больше нуля, в противном случае семафор считается занятым.
Операции над семафором • Пусть s – семафор, тогда над ним можно определить следующие атомарные операции: P(s) // захватить семафор { если s >0 то s = s – 1; // поток продолжает работу иначе ждать освобождения s; // поток переходит в состояние ожидания } V(s) // освободить семафор { если потоки ждут освобождения s то освободить один поток; иначе s = s + 1; }
• Из определения операций над семафором видно, что если поток выдает операцию P и значение семафора больше нуля, то значение семафора уменьшается на 1 и этот поток продолжает свою работу, в противном случае поток переходит в состояние ожидания до освобождения семафора другим потоком. • Вывести из состояния ожидания поток, который ждет освобождения семафора, может только другой поток, который выдает операцию V над этим же семафором.
Определение семафора Дейкстры • Семафор с операциями P и V называется семафором Дейкстры, голландского математика, который первым использовал семафоры для решения задач синхронизации.
Сильный и слабый семафоры • Потоки, ждущие освобождения семафора, выстраиваются в очередь к этому семафору. • Дисциплина обслуживания очереди зависит от конкретной реализации. • Очередь может обслуживаться как по правилу FIFO, так и при помощи более сложных алгоритмов, учитывая приоритеты потоков. • Если очередь семафора обслуживается по алгоритму FIFO, то семафор называется сильным, иначе - слабым.
Двоичный и считающий семафоры • Семафор, который может принимать только значения 0 или 1, называется двоичным или бинарным семафором. • Семафор, значение которого может быть больше 1, обычно называют считающими семафором.
Решение проблемы взаимного исключения для двух потоков при помощи семафора Semaphor s = 1; // семафор свободен void thread_1( ) void thread_2( ) { { before. Critical. Section_1(); before. Critical. Section_2(); P(s); // захватить critical. Section_1(); critical. Section_2(); V(s); // освободить after. Critical. Section_1(); after. Critical. Section_2(); } }
Решение проблемы условной синхронизации для двух потоков при помощи семафора Semaphor s = 0; // семафор занят void thread_1( ) void thread_2( ) { { before. Event_1(); before. Event_2(); P(s); // wait V(s); // signal after. Event_1(); after. Event_2(); } }
5. 5. Примитив синхронизации Semaphore (семафор)
Схема реализации примитива синхронизации семафор class Semaphore { int count; // счетчик Thread. Queue tq; // очередь потоков public: Semaphore(int& n): count(n) {} ~Semaphore() {. . . } void wait(); // закрыть семафор void signal(); // открыть семафор };
void Semaphore: : wait() // закрыть семафор { disable. Interrupt(); if (count > 0) --count; else tq. enqueue. Thread(current. Thread()); enable. Interrupt(); }
void Semaphore: : signal() // открыть семафор { disable. Interrupt(); if (!tq. dequeue. Thread()) ++count; enable. Interrupt(); }
5. 6. Объекты синхронизации и функции ожидания в Windows
Объекты синхронизации • В операционных системах Windows объектами синхронизации называются объекты ядра, которые могут находиться в одном из двух состояний: – сигнальном (signaled); – несигнальном (nonsignaled).
Классификация объектов синхронизации • Объекты синхронизации могут быть разбиты на три класса: – собственно объекты синхронизации, которые служат только для решения проблемы синхронизации параллельных потоков. К таким объектам синхронизации в Windows относятся: • мьютекс (mutex); • событие (event); • семафор (semaphore); – ожидающий таймер (waitable timer); – объекты, которые переходят в сигнальное состояние по завершении своей работы или при получении некоторого сообщения • Например, потоки и процессы. Пока эти объекты выполняются, они находятся в несигнальном состоянии. Если выполнение этих объектов заканчивается, то они переходят в сигнальное состояние.
Функции ожидания • Функции ожидания в Windows это такие функции, которые используются для блокировки исполнения потоков в зависимости от состояния объекта синхронизации, который является параметром функции ожидания. • При этом блокировка потоков выполняется следующим образом: – если объект синхронизации находится в несигнальном состоянии, то поток, вызвавший функцию ожидания, блокируется до перехода этого объекта синхронизации в сигнальное состояние; – если объект синхронизации находится в сигнальном состоянии, то поток, вызвавший функцию ожидания, продолжает свое исполнение, а объект синхронизации, как правило, переходит в несигнальное состояние.
Функции ожидания в Windows • Wait. For. Single. Object – ждет перехода в сигнальное состояние одного объекта синхронизации; • Wait. For. Multiple. Objects – ждет перехода в сигнальное состояние одного или нескольких объектов из массива объектов синхронизации.
5. 7. Критические секции в Windows
Назначение объекта критическая секция • Для решения проблемы взаимного исключения для параллельных потоков, выполняемых в контексте одного процесса, в операционной системе Windows предназначены объекты типа CRITICAL_SECTION. • Объект типа CRITICAL_SECTION не является объектом ядра операционной системы, так как предполагается его использование только в контексте одного процесса. • Это повышает скорость работы этого примитива синхронизации, так как не требуется обращаться к ядру операционной системы.
Функции для работы с объектами типа CRITICAL_SECTION • Initialize. Critical. Section – инициализация объекта; • Enter. Critical. Section – вход в критическую секцию; • Try. Enter. Critical. Section – попытка входа в критическую секцию; • Leave. Critical. Section – выход из критической секции; • Delete. Critical. Section – завершение работы с объектом;
5. 8. Мьютексы в Windows
Назначение мьютексов • Для решения проблемы взаимного исключения для параллельных потоком, выполняющихся в контексте разных процессов, в операционной системе Windows предназначен объект ядра мьютекс (mutex). • Мьютекс находится в сигнальном состоянии, если он не принадлежит ни одному потоку. • В противном случае мьютекс находится в несигнальном состоянии. • Одновременно мьютекс может принадлежать только одному потоку.
Функции для работы с мьютексами • Create. Mutex – создание мьютекса; • Open. Mutex – получение доступа к существующему мьютексу; • Release. Mutex – освобождение мьютекса (переход мьютекса в сигнальное состояние); • Wait. For. Single. Object или Wait. For. Multiple. Objects – захват мьютекса (ожидание сигнального состояния мьютекса).
5. 9. События в Windows
Назначение событий • В операционных системах Windows события описываются объектами ядра Event. • Объекты типа Event предназначены для решения задачи условной синхронизации.
Типы событий • В Windows различают два типа событий: – события с ручным сбросом; – события с автоматическим сбросом.
События с ручным сбросом • Событие с ручным сбросом можно перевести в несигнальное состояние только посредством вызова функции Reset. Event.
События с автоматическим сбросом • Событие с автоматическим сбросом переходит в несигнальное состояние как при помощи функции Reset. Event, так и при помощи функций ожидания Wait. For. Single. Object или Wait. For. Multiple. Objects. • Если события с автоматическим сбросом ждут несколько потоков, используя функцию Wait. For. Single. Object, то из состояния ожидания освобождается только один из этих потоков.
Функции для работы с событиями Create. Event – создание события; Open. Event – получение доступа к существующему событию; Set. Event – перевод события в сигнальное состояние; Reset. Event – перевод события в несигнальное состояние; Pulse. Event – освобождение нескольких потоков, ждущих сигнального состояния события с ручным сбросом; • Wait. For. Single. Object или Wait. For. Multiple. Objects – ожидание наступления события (перехода события в сигнальное состояние). • • •
5. 10. Семафоры в Windows
Назначения семафоров • Семафоры в операционных системах Windows описываются объектами ядра Semaphore. • При помощи семафоров может решаться как задача взаимного исключения, так и задача условной синхронизации. • Поэтому семафор часто называют универсальным примитивом синхронизации.
Состояния и значения семафора • Семафор находится в сигнальном состоянии, если его значение больше нуля. • В противном случае семафор находится в несигнальном состоянии.
Функции для работы с семафорами • Create. Semaphore – создание семафора; • Open. Semaphore – получение доступа к существующему семафору; • Release. Semaphore – увеличение значения семафора на положительное число; • Wait. For. Single. Object или Wait. For. Multiple. Objects – ожидание перехода семафора в сигнальное состояние.