WikiSort.ru - Не сортированное

ПОИСК ПО САЙТУ | о проекте
Изображение 1: Попытка одновременного удаления двух узлов i и i + 1 приводит к сохранению узла i + 1.

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

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

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

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

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

Мьютексы в Win32 API

Win32 API в Windows имеет две реализации мьютексов — собственно мьютексы[1], имеющие имена и доступные для использования между разными процессами, и критические секции[2], которые могут использоваться только в пределах одного процесса. Для каждого из этих двух типов мьютексов используются свои функции захвата и освобождения.

Критическая секция в Windows по возможности блокируется без использования вызова режима ядра (аналогично спинлоку), но при невозможности такой блокировки поток запрашивает ядро.

Мьютексы в Unix-подобных системах

Мьютекс в стандартной библиотеке Pthreads может использоваться в одном процессе или в разных, но в любом случае всем использующим процессам требуется доступ к памяти, в которой он размещён. Такой мьютекс может иметь один из следующих типов[3]:

  • PTHREAD_MUTEX_NORMAL — нет контроля повторного захвата тем же потоком (англ. thread);
  • PTHREAD_MUTEX_RECURSIVE — повторные захваты тем же потоком допустимы, ведётся счётчик таких захватов;
  • PTHREAD_MUTEX_ERRORCHECK — повторные захваты тем же потоком вызывают немедленную ошибку.

Мьютексы в языке Си

Последний стандарт языка Си (ISO/IEC 9899:2011[4]) определяет тип mtx_t и функции для работы с ним, которые должны быть доступны, если макрос __STDC_NO_THREADS__ не был определён компилятором. Семантика и свойства мьютексов в целом совпадают со стандартом POSIX:

  • mtx_plain — нет контроля повторного захвата тем же потоком;
  • mtx_recursive — повторные захваты тем же потоком допустимы, ведётся счётчик таких захватов;
  • mtx_timed — поддерживается захват мьютекса с тайм-аутом (следует отметить, что, в отличие от стандарта POSIX, поддержка этого свойства мьютекса не является опциональной).

Возможность использования мьютексов в разделяемой памяти различных процессов в стандарте Си11 не рассматривается.

Пример использования простого мьютекса на чистом Си:

char mut1 = 0;

// функция использующая общие ресурсы
void func() {
    // while(mut1) {}  в этом случае функция будет ждать, пока не завершится функция в другом потоке
    if (!mut1){ // в этом случае функция не выполнится, если уже выполняется эта же функция из др. потока
        mut1 = 1;
        // код с использованием общих ресурсов
        mut1 = 0;
    }
}

// Пример метода run 1го потока
void run1() {
    while (1) {
        func();
        sleep(1);
    }
}

// Пример метода run 2го потока
void run2() {
    func();
}

Мьютексы в языке C++

Стандарт языка C++ (ISO/IEC 14882:2011[5]) определяет различные классы мьютексов:

  • mutex — нет контроля повторного захвата тем же потоком;
  • recursive_mutex — повторные захваты тем же потоком допустимы, ведётся счётчик таких захватов;
  • timed_mutex — нет контроля повторного захвата тем же потоком, поддерживается захват мьютекса с тайм-аутом;
  • recursive_timed_mutex — повторные захваты тем же потоком допустимы, ведётся счётчик таких захватов, поддерживается захват мьютекса с тайм-аутом.

Следует отметить библиотеку Boost, которая обеспечивает:

  • реализацию мьютексов, совместимых по интерфейсу со стандартом C++11 для компиляторов и платформ, которые не поддерживают этот стандарт;
  • реализацию дополнительных классов мьютексов: shared_mutex и др., которые позволяют захватывать мьютекс для совместного владения несколькими потоками только для чтения данных.

Примечания

  1. Create Mutex. Проверено 20 декабря 2010. Архивировано 14 февраля 2012 года.
  2. Critical sections. Проверено 20 декабря 2010. Архивировано 14 февраля 2012 года.
  3. pthread_mutexattr_settype(3). Проверено 20 декабря 2010. Архивировано 14 февраля 2012 года.
  4. ISO/IEC 9899:2011 — Information technology — Programming languages — C
  5. ISO, ISO/IEC 14882:2011 Information technology — Programming languages — C++

См. также

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

Другой контент может иметь иную лицензию. Перед использованием материалов сайта WikiSort.ru внимательно изучите правила лицензирования конкретных элементов наполнения сайта.

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии