текст презентациии

20 Февраль 2014 →

Мьютекс (англ. mutex, от mutual exclusion — «взаимное исключение») — одноместный семафор, служащий в программировании для синхронизации одновременно выполняющихся потоков.

Мьютексы — это один из вариантов семафорных механизмов для организации взаимного исключения. Они реализованы во многих ОС, их основное назначение — организация взаимного исключения для потоков из одного и того же или из разных процессов.

Мьютексы — это простейшие двоичные семафоры, которые могут находиться в одном из двух состояний — отмеченном или неотмеченном (открыт и закрыт соответственно). Когда какой-либо поток, принадлежащий любому процессу, становится владельцем объекта mutex, последний переводится в неотмеченное состояние. Если задача освобождает мьютекс, его состояние становится отмеченным.

ЗАДАЧА MUTEX

защита объекта от доступа к нему других потоков, отличных от того, который завладел мьютексом. В каждый конкретный момент только один поток может владеть объектом, защищённым мьютексом. Если другому потоку будет нужен доступ к переменной, защищённой мьютексом, то этот поток засыпает до тех пор, пока мьютекс не будет освобождён.

Цель использования MUTEX ------ защита данных от повреждения в результате асинхронных изменений (состояние гонки), однако могут порождаться другие проблемы — такие, как взаимная блокировка.

Причины возникновения mutex----

Параллельные потоки — это очень удобно. Класс Thread неплохо делает свою работу на многих платформах. Однако, самостоятельно работающий поток, который не имеет связи с внешним миром (другими потоками), вряд ли полезен в реальном приложении. Вычисления для этого и распараллеливаются, чтобы, так сказать, в несколько рук (потоков) выполнить одну задачу. Возникает задача синхронизации потоков.

Например, в программе есть некоторая строковая переменная, хранящая описание текущего состояния. Это состояние может, например, выводиться в нижней полоске рабочего окна. Теперь представим, что в программе есть два параллельно работающих потока. Первый занимается получением данных из сети, а второй — обработкой базы данных. Допустим, настал некоторый момент времени, когда первый поток принял данные из сети и хочет об этом отрапортовать в строке состояния, записав туда "Принято 16384 байт". Приблизительно в этот же момент второй поток завершил периодическую проверку базы данных и также желает об этом сообщить пользователю строкой "База данных проверена". Операция копирования строки не является атомарной, то есть нет никакой гарантии, что во время ее выполнения процессор не переключится на какой-то другой поток, и операция копирования не будет прервана посреди работы. Итак, когда поток номер 1 успел записать в строку состояния слово "Принято", может так случиться, что процессор активирует поток номер 2, который также начнет запись своей строки и добавит к уже записанному "Принято" строку "База данных про", но будет прерван первым потоком и т.д. В итоге в переменная может содержать кашу типа "ПрияноБаза данных 1про6в3ерена84 байт". Вывод такой — результат полностью непредсказуем.

Для решения подобного вроде проблем в мире параллельного программирования существует такое понятие, как блокировка. Суть ее в том, что когда один процесс захватывает блокировку, то все остальные процессы, пытающиеся ее захватить после, будут блокированы до тех пор, пока первый процесс ее не отпустит. Это похоже на дверь в комнату: представим, что наша переменная globalStatus находится в комнате с одной дверью и ключом внутри. Если дверь открыта (блокировка свободна), то в комнате никого нет (никто не работает с переменной). Когда процесс заходит в комнату, он запирает дверь изнутри (захватывает блокировку). После этого процесс может спокойно работать с переменной как угодно долго, так как гарантированно никто другой не войдет в комнату, так как она заперта изнутри, и не будет мешать ему работать с переменной.

Это была идея простейшей блокировки, которую часто называют мьютекс (mutex). Сейчас мы рассмотрим реализацию такой блокировки на С++, которая будет работать в Windows и UNIX.

КЛАСС MUTEX

Класс Mutex получился весьма простой, в виде единственного файла mutex.h. Пространство имен (namespace) называется ext для простоты.

0. // Интерфейс класса Mutex.

// Класс задумывался как маленький и быстрый, поэтому все

// определено прямо в заголовочном файле, и все функции

// объявлены принудительно inline. Это должно уберечь

// от ошибок и предупреждений о двойных символах при

// включении mutex.h в несколько модулей.

// Деструктор объявлен как не виртуальный из-за тех же

// соображений эффективности. Если вы планируете

// наследоваться от этого класса, то лучше сделать

// деструктор виртуальным, так как наследование от класса

// с не виртуальным деструктором потенциально опасно

// с точки зрения утечек памяти и является одним из

// больших "no-no" в С++.

// Функция захвата блокировки (вход в комнату и запирание

// двери ключом изнутри).

// Функция освобождения блокировки (отпирание двери и

// выход из комнаты)

Класс mutex является примитивом синхронизации, который может использоваться для защиты разделяемых данных от одновременного доступа нескольких потоков.

mutex предлагает эксклюзивую, нерекурсивную семантику владения:

Вызывающий поток владеет мьютексом со времени успешного вызова lock или try_lock, и до момента вызова unlock.

Пока поток владеет мьютексом, все остальные потоки при попытке завладения им блокируются на вызове lock или получают значение false при вызове try_lock.

Вызывающий поток не должен владеть мьютексом до вызова lock или try_lock.

Поведение программы не определено, если занятый некоторым потоком мьютекс разрушается. Класс mutex является некопируемым.


See also:
Для студента
Похожие записи

Комментарии закрыты.