«Безопасная» обработка Mutex? - PullRequest
8 голосов
/ 07 февраля 2012

Я постоянно читаю из файла, отображенного в памяти, в который пишет другой процесс, и использую мьютекс для синхронизации этой операции. В моих нескольких тестах до сих пор это работало просто отлично, но ... что если мое приложение аварийно завершает работу сразу после получения мьютекса и перед его освобождением? Есть ли способ гарантировать освобождение мьютекса даже в случае такого сбоя?

Кроме того, как бы я справился со сбоем другого процесса, который еще не освободил мьютекс? Нужно ли обрабатывать AbandonedMutexException каждый раз, когда я вызываю mutex.WaitOne ()?

Прямо сейчас я делаю это так:

public MyState GetState()
{
    MyState state = new State();
    this._mutex.WaitOne();
    try
    {
        state.X = this._mmView.ReadSingle(0);
        state.Y = this._mmView.ReadSingle(4);
        [..]
    }
    finally
    {
        this._mutex.ReleaseMutex();
    }
    return state;
}

_mmView - это MemoryMappedViewAccessor, который я создал ранее. Весь этот метод GetState () вызывается каждый кадр как часть игрового цикла, так что каждые несколько миллисекунд.

PS: Кроме того, есть ли другие очевидные проблемы, по которым это может не получиться, о которых я уже не упоминал?

Ответы [ 2 ]

11 голосов
/ 07 февраля 2012

Eugen ответ правильный - операционная система выпустит мьютекс для вас. Теперь подумайте о последствиях этого факта:

  • Вы удалили мьютекс, чтобы никто не изменил состояние, пока вы читали, или состояние чтения, пока вы мутировали. Давайте предположим, что последний.
  • Другое приложение хочет прочитать состояние, поэтому оно пытается получить мьютекс. Вынужден ждать.
  • Вы изменили какое-то состояние, а затем потерпели крах.
  • Операционная система освободила мьютекс.
  • Другое приложение теперь немедленно получает мьютекс, и теперь эффективно читает состояние "пока" другой процесс его мутирует . Тот факт, что другой процесс теперь мертв и ушел, означает, что фиктивное состояние теперь будет длиться навсегда , и процесс чтения, вероятно, сам по себе рухнет и ужасно умрет. Вы только что победили систему безопасности, предоставляемую мьютексом .

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

Во-первых, не попадите в эту ситуацию. Решение проблемы: не вылетает, если вы вынули мьютекс для записи . Если вы не пишете программы, которые аварийно завершают работу, вам не нужно беспокоиться об этом, потому что этого не произойдет. Так что просто не пишите программы, которые когда-либо вылетали.

2 голосов
/ 07 февраля 2012

Когда процесс завершается с владением мьютексом, ОС автоматически освобождает мьютекс для вас. Попробуйте это, получив мьютекс, а затем raise new WhateverException() - другой процесс продолжится.

То же самое относится ко всем примитивам синхронизации AFAIK

...