- •ОПЕРАЦИОННЫЕ СИСТЕМЫ
- •Домен приложения
- •Домен приложения
- •В пространстве имен System.Threading
- •Обзор пространства имен System.Threading
- •Класс Thread. Общая характеристика
- •Нестатические члены класса Thread
- •Interrupt()
- •Создание потока
- •Приоритеты потоков
- •Класс ThreadState
- •Диаграмма состояний потока
- •Синхронизация
- •Класс Monitor и инструкция lock
- •Класс Semaphore используется для управления доступом к пулу ресурсов
- •Семафоры бывают двух типов:
- •public sealed class Mutex : WaitHandle
- •Мьютексы бывают двух типов:
Класс ThreadState
определяет набор всех возможных состояний выполнения для потока
|
|
|
|
Поток создается в среде CLR |
Unstarted |
||
|
|
||
Поток вызывает метод Start |
Running |
||
Поток начинает выполнение |
Running |
||
Поток вызывает метод Sleep |
WaitSleepJoin |
||
Поток вызывает метод Wait для другого объекта |
WaitSleepJoin |
||
Поток вызывает метод Join для другого потока |
WaitSleepJoin |
||
Другой поток вызывает метод Interrupt |
Running |
||
Другой поток вызывает метод Suspend |
SuspendRequested |
||
Поток отвечает на запрос метода Suspend |
Suspended |
||
Другой поток вызывает метод Resume |
Running |
||
Другой поток вызывает метод Abort |
AbortRequested |
||
Поток отвечает на запрос метода Abort |
Stopped |
||
Поток завершен |
Stopped |
||
|
|
|
|
Диаграмма состояний потока
Синхронизация
Процесс координации потоков называется синхронизацией. В основе синхронизации лежит понятие блокировки, т.е.
управление доступом к некоторому блоку кода в объекте.
Синхронизация в С# поддерживается ключевым словом lock. Формат использования инструкции lock таков:
lock(object) { // Инструкции, подлежащие синхронизации.
}
Здесь параметр object - ссылка на синхронизируемый объект.
Если нужно синхронизировать только один элемент, фигурные
скобки можно опустить.
Инструкция lock должна использоваться только для объектов, определенных как private или internal, иначе внешние к данной
программе потоки смогут получить блокировку и не снимать ее.
Пример ThreadSincLock, AlterLoc
Чтобы заблокировать static-метод, достаточно использовать
инструкцию lock в следующем формате: lock(typeof(class) ) { // Блокируемый код}
Здесь class представляет собой имя класса, в котором
содержится
static-метод, подлежащий блокировке.
Класс Monitor и инструкция lock
Ключевое слово lock — это сокращенный вариант использования средств синхронизации, определенных в классе Monitor, принадлежащем пространству имен System.Threading.
В классе Monitor определено несколько методов синхронизации.
public static void Enter(object syncOb) |
для получения возможности |
|
блокировки для некоторого объекта |
public static void Exit(object syncOb) public static bool TryEnter(object syncOb)
для снятия блокировки
возвращает значение true, если вызывающий поток получает блокировку для объекта syncOb, и
значение false в противном случае.
public static bool Wait(object waitOb)
public static bool Wait(object waitOb, int milliseconds)
public static void Pulse(object waitOb)
выполнение потока временно блокируется
ожидание до уведомления или до истечения периода времени, заданного
в миллисекундах
возобновление выполнения потока, стоящего первым в очереди потоков,
пребывающих в режиме ожидания
public static void PulseAll(object waitOb) возобновление всех ожидающих потоков
Класс Semaphore используется для управления доступом к пулу ресурсов
public sealed class Semaphore : WaitHandle
Метод public virtual bool WaitOne() блокирует текущий поток
до получения сигнала объектом WaitHandle. Возвращает значение true, когда текущий экземпляр получает сигнал. Если текущий экземпляр не получает сигнал, метод WaitOne() не
возвращает значения.
Метод public int Release() освобождает семафор. Возвращает значение семафора перед вызовом Release().
Счетчик на семафоре уменьшается на единицу каждый раз,
когда
в семафор входит поток, и увеличивается на единицу, когда поток освобождает семафор. Когда счетчик равен нулю,
последующие запросы блокируются, пока другие потоки не
освободят семафор. Когда семафор освобожден всеми потоками, счетчик имеет максимальное значение, заданное при создании
семафора. Release() для семафора с максимальным значением
Семафоры бывают двух типов:
•
•
локальные семафоры именованные системные.
При создании объекта Semaphore с помощью конструктора, позволяющего передавать параметр с именем семафора, объект связывается с имеющим данное имя семафором операционной системы. Именованные системные семафоры доступны в пределах всей операционной системы и могут быть использованы для синхронизации действий процессов. Можно создать несколько объектов Semaphore, представляющих один и тот же системный именованный семафор, и использовать метод OpenExisting для открытия существующего именованного системного семафора.
Локальный семафор существует только внутри одного процесса. Он может использоваться любым потоком в процессе, имеющим ссылку на локальный объект Semaphore. Каждый объект Semaphore является отдельным локальным семафором.
Пример ThreadSem
public sealed class Mutex : WaitHandle
примитив, который предоставляет эксклюзивный доступ к общему
ресурсу только одному потоку синхронизации.
Если поток получает мьютекс, второй поток, желающий получить этот мьютекс, приостанавливается до тех пор, пока первый поток не освободит мьютекс.
Для запроса на владение мьютексом используется метод public virtual bool WaitOne(int millisecondsTimeout)
millisecondsTimeout - время ожидания в миллисекундах или Timeout.Infinite (-1) в случае неограниченного времени ожидания. Возвращает true при получении сигнала текущим экземпляром; в противном случае – false.
Поток должен вызвать метод
public void ReleaseMutex() ,
чтобы освободить мьютекс один раз.
Класс Mutex выполняет идентификацию потоков, т.е. мьютекс может освобождаться только потоком, получившим его. Класс Semaphore не обеспечивает потоковой идентификации. Если поток завершается, владея мьютексом, то мьютекс
называется брошенным. Состояние мьютекса задается сигнальным, и мьютекс переходит во владение следующему ожидающему потоку.
Мьютексы бывают двух типов:
•Локальные мьютексы (без имени). Существуют только внутри одного процесса. Может использоваться любым потоком в процессе, который содержит ссылку на объект Mutex, представляющий мьютекс. Каждый неименованный объект Mutex представляет отдельный локальный мьютекс.
•Именованные системные доступны в пределах всей операционной системы и могут быть использованы для синхронизации действий процессов. Можно создать объект Mutex, представляющий именованный системный мьютекс, используя конструктор с поддержкой имен. Объект операционной системы может быть создан в то же время, или существовать до создания объекта Mutex. Можно создать несколько объектов Mutex, представляющих один и тот же именованный системный мьютекс, и использовать метод OpenExisting для открытия существующего именованного системного мьютекса.
Пример ThreadMutex