Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабораторные работы / Метода по 4 лабе

.pdf
Скачиваний:
0
Добавлен:
29.09.2026
Размер:
1 Мб
Скачать
☆
Сначала создаем объект мьютекса: Mutex mutexObj = new Mutex().
Основную работу по синхронизации выполняют методы WaitOne() и
ReleaseMutex(). Метод mutexObj.WaitOne() приостанавливает выполнение
потока до тех пор, пока не будет получен мьютекс mutexObj.
После выполнения всех действий, когда мьютекс больше не нужен, поток освобождает его с помощью метода mutexObj.ReleaseMutex()
Таким образом, когда выполнение дойдет до вызова
mutexObj.WaitOne(), поток будет ожидать, пока не освободится мьютекс. И
после его получения продолжит выполнять свою работу.
Пример 6.
Мьютексы бывают двух типов: локальные мьютексы, которые являются неименованными, и именованные системные мьютексы. Локальный мьютекс существует только в вашем процессе. Он может использоваться любым потоком в процессе, имеющим ссылку на объект Mutex, представляющий мьютекс. Каждый
неименованный объект Mutex представляет отдельный локальный мьютекс.
Именованные системные мьютексы видимы во всей операционной системе и могут использоваться для синхронизации действий процессов. Можно создать
объект Mutex, представляющий именованный системный мьютекс, с помощью конструктора, принимающего имя. Объект операционной системы может быть создан одновременно, или он может существовать до создания объекта Mutex. Можно создать сразу несколько объектов Mutex, представляющих один и тот именованный системный мьютекс, а также открывать именованный системный мьютекс с помощью метода OpenExisting.
2.4 Семафоры
Еще один инструмент, который предлагает платформа .NET для синхронизации потоков, представляют семафоры. Семафор позволяют ограничить число потоков, которые могут одновременно обращаться к ресурсу или пулу ресурсов.
Счетчик для семафора уменьшается каждый раз, когда поток берет семафор, и увеличивается, когда поток освобождает семафор. Если значение счетчика семафора равно нулю, последующие запросы блокируются до освобождения семафора другими потоками. Когда семафор освобожден всеми потоками, счетчик семафора будет иметь максимальное значение, указанное при создании семафора.
Пример 7.
Есть четыре читателя, которые приходят в библиотеку три раза в день и что-то там читают. И пусть у нас будет ограничение, что единовременно в библиотеке не может находиться больше двух читателей. Данную задачу очень легко решить с помощью семафоров.
В данной программе читатель представлен классом Reader. Он инкапсулирует всю функциональность, связанную с потоками, через переменную
Thread myThread.
Для создания семафора используется класс Semaphore:
static Semaphore sem = new Semaphore(2, 2);
Его конструктор принимает два параметра: первый указывает, какое число объектов изначально может взять семафор, а второй параметр указывает, какое максимальное число объектов будет использовать данный семафор. В данном случае у нас только два читателя могут одновременно находиться в библиотеке, поэтому максимальное число равно 2.
Основной функционал сосредоточен в методе Read, который и выполняется в потоке. В начале для ожидания получения семафора используется метод sem.WaitOne(). После того, как освободится семафор, данный поток забирает семафор и начинает выполнять все дальнейшие действия. После окончания чтения поток высвобождает семафор с помощью метода
sem.Release(). После этого семафор освобождается, и может быть взят другим
потоком.
А в методе Main остается только создать читателей, которые запускают соответствующие потоки.
Класс Semaphore не обеспечивает идентификацию потоков при вызовах
WaitOne или Release. Ответственность за то, чтобы потоки не освободили
семафор слишком много раз, лежит на программисте. Например, предположим, что семафор имеет максимальное значение счетчика равное двум, а два потока A и B входят в семафор. Если ошибка программирования в потоке B приводит к вызову метода Release дважды, оба вызова будут выполнены. Счетчик на
семафоре переполнен, и если поток A вызывает Release, создается исключение
SemaphoreFullException.
Семафоры имеют два типа: локальные семафоры и именованные системные семафоры. При создании объекта Semaphore с помощью конструктора, который принимает имя, он связывается с семафором операционной системы с этим именем. Именованные системные семафоры видимы во всей операционной системе и могут использоваться для синхронизации действий процессов. Можно создать несколько объектов
Semaphore, представляющих один и тот же именованный системный семафор, а
метод OpenExisting можно использовать для открытия существующего именованного системного семафора.
Локальный семафор существует только в пределах процесса. Его может использовать любой поток в этом процессе, имеющий ссылку на локальный объект Semaphore. Каждый объект Semaphore является отдельным локальным семафором.
2.5 Барьер
Барьер - это определяемый пользователем примитив синхронизации, позволяющий нескольким потокам (которые называются участниками) параллельно осуществлять поэтапную работу с алгоритмом. Каждый участник выполняется до достижения точки барьера в коде. Барьер означает окончание одного этапа работы. Когда участник достигает барьера, он блокируется до тех пор, пока все участники не достигнут этого барьера. Когда все участники достигли барьера, можно при необходимости вызвать действие следующего этапа.
Пример 8.
При создании экземпляра Barrier необходимо указать количество участников. Можно также динамически добавлять или удалять участников в любое время. Например, если один участник решил свою часть задачи, можно сохранить результат, остановить выполнение этого потока и вызвать
Barrier.RemoveParticipant, чтобы уменьшить число участников барьера. При
добавлении участника путем вызова Barrier.AddParticipant возвращаемое значение определяет номер текущего этапа, что может быть полезно для инициализации действий нового участника.
Объект Barrier приостанавливает параллельное выполнение отдельных потоков, пока все потоки не достигнут этого барьера. Это полезно в тех случаях, когда параллельная операция имеет четко определенные этапы, по каждому из которых требуется синхронизация между потоками. В нашем примере операция осуществляется в два этапа. На первом этапе каждый поток выполняет какие-то свои действия. Каждый поток, который завершает выполнение своих действий, сообщает барьеру о завершении и переходит в режим ожидания. Когда все потоки отправят барьеру сигналы, блокировка снимается и начинается второй этап. Этот барьер нужен, например, для того, чтобы каждый поток на втором этапе получила доступ ко всем данным, созданным до этого момента. Без этого барьера первый поток, выполнивший свою работу, может начать использовать данные, которые еще не обработаны другими потоками. Этот подход позволяет синхронизировать любое количество этапов.
4 Содержание отчета по лабораторной работе
Отчет по лабораторной работе должен содержать следующие сведения:
цель работы;
примеры выполнения команд; пояснительные комментарии к командам.