Мониторы и повторный вход (поясняет разницу между кодом повторного входа и блокировкой повторного входа)

Чтение по замкам в C #. Я вижу, что возможность получить блокировку одного и того же объекта несколько раз считается возможной, потому что мониторы повторно въезжают. Определение реентерабельного кода, как оно определено в Википедии, не подходит в этом контексте. Не могли бы вы помочь мне понять, что такое повторный вход в контексте C # и как он применяется к мониторам? Из того, что я понял, когда поток получил блокировку, он не откажется от блокировки, когда находится в середине критического раздела - даже если он уступит ЦП ... в результате чего ни один другой поток не сможет получить монитор .. где повторное вхождение в кадр?


person Aadith Ramia    schedule 06.01.2016    source источник
comment
Повторите редактирование: повторный вход появляется, когда поток, который уже удерживает блокировку, вызывает lock или Monitor.Enter снова для того же объекта. Вы можете подумать, что это приведет к взаимной блокировке, но это удается и просто реализует внутренний счетчик. Затем один и тот же поток должен вызвать Monitor.Exit (или выйти из области lock) несколько раз, чтобы действительно снять блокировку.   -  person Kirill Shlenskiy    schedule 06.01.2016
comment
Википедия говорит: - В вычислениях компьютерная программа или подпрограмма называется реентерабельной, если ее можно прервать в середине выполнения, а затем безопасно вызвать снова ... в рассматриваемом сценарии прерывания нет ... не так ли?   -  person Aadith Ramia    schedule 06.01.2016
comment
Нет, когда дело доходит до повторного входа блокировок, говорить о перебоях не приходится. Вы смешиваете две разные концепции: повторный вход метода (обсуждается в той статье в Википедии, которую вы связали) и повторный вход блокировки (см. en.wikipedia.org/wiki/Reentrant_mutex). Каждый раз, когда вы слышите слово повторное вхождение, примененное к lock, Monitor, Mutex или любому другому примитиву синхронизации, это обычно относится к способности потока , уже удерживающего блокировку, снова получить указанную блокировку (вы можете думать об этом как о рекурсии блокировки).   -  person Kirill Shlenskiy    schedule 06.01.2016


Ответы (2)


@Zbynek Vyskovsky - kvr000 уже объяснил, что означает повторный вход в отношении Monitor.

Википедия определяет «повторно входимый мьютекс» (рекурсивная блокировка) как:

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

Вот небольшой пример, который поможет вам визуализировать концепцию:

void MonitorReentrancy()
{
    var obj = new object();

    lock (obj)
    {
        // Lock obtained. Must exit once to release.
        // No *other* thread can obtain a lock on obj
        // until this (outermost) "lock" scope completes.

        lock (obj) // Deadlock?
        {
            // Nope, we've just *re-entered* the lock.
            // Must exit twice to release.

            bool lockTaken = false;

            try
            {
                Monitor.Enter(obj, ref lockTaken); // Deadlock?

                // Nope, we've *re-entered* lock again.
                // Must exit three times to release.
            }
            finally
            {
                if (lockTaken) {
                    Monitor.Exit(obj);
                }

                // Must exit twice to release.
            }
        }

        // Must exit once to release.
    }

    // At this point we have finally truly released
    // the lock allowing other threads to obtain it.
}
person Kirill Shlenskiy    schedule 06.01.2016

На самом деле реентерабельность имеет много значений.

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

person Zbynek Vyskovsky - kvr000    schedule 06.01.2016
comment
Спасибо. Что еще может означать повторное вхождение? - person Aadith Ramia; 06.01.2016
comment
Например, функция может быть вызвана несколькими потоками одновременно (проблемы с некоторыми оригинальными API-интерфейсами POSIX - некоторые функции не позволяли этого - localtime() функция). Другое значение состоит в том, что функцию можно прервать и ее можно повторно запустить без каких-либо побочных эффектов. - person Zbynek Vyskovsky - kvr000; 06.01.2016