2010-11-03 5 views
4
void MethodA() 
{ 
    Monitor.Enter(this); 
    if(someCondition) 
    { 
     Monitor.Exit(this); 
     // This point 
     MethodB(); 
    } 
    else 
    { 
     // Set some values only 
Monitor.Exit(this); 
    } 
} 

Если у меня есть вышеупомянутый метод, который может быть вызван в нескольких нитей:Надлежащее использование Monitor.Exit

  • Предположим, поток 1 находится в //This point
  • Другой поток входит Monitor.Enter в то время как поток 1 по-прежнему на //This point
  • Будет ли эта остановка MethodB быть выполненной? Если да, есть способ получить MethodB для выполнения.

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

+0

Если исключение произойдет, блокировка никогда не будет выпущена, используйте ее только в 'try .. finally' – Andrey

ответ

1

Поскольку someCondition не передается в качестве параметра, я могу предположить, что someCondition может быть изменена в любое время (возможно, переменная экземпляра для класса). Таким образом, я бы написать код так:

void MethodA() 
{ 
    if (someCondition) 
    { 
     bool conditionReached = false; 

     Monitor.Enter(this); 
     try 
     { 
      if (someCondition) 
      { 
       conditionReached = true; 
      } 
     } 
     finally 
     { 
      Monitor.Exit(this); 
     } 

     if (conditionReached) 
     { 
      MethodB(); 
     } 
    } 
} 

Если нет, чем предыдущий ответ с condition объявленной локально подойдет вам.

+0

Это мое положение! Благодаря!! – SimpleOne

+1

В исходном коде блокировка специально получена для оценки someCondition, тогда как этот код будет оцениваться вне блокировки. Этот подход с двойной проверкой позволяет избежать ввода блокировки, если условие ложно, но исходный код фактически сделал что-то в области блокировки, если условие ложно. Наконец, подход «двойной проверки» также потенциально уязвим для редкой расовой неудачи из-за отсутствия барьера памяти вокруг первой оценки someCondition. Блокировка блокирует помехи памяти. –

+0

Дэн прав. Помимо того, что он ведет себя иначе, чем оригинал, он также имеет тонкую проблему с барьером памяти. –

8

Откладывая вопрос об использовании «это» как замок (плохая практика, так как она подвергает замок публично), эта форма чище и безопаснее (снимает блокировку, если исключение):

void MethodA() 
{ 
    bool condition; 
    lock(this) 
    { 
    condition = someCondition; 
    if(!condition) 
    { 
     // Set some values only 
    } 
    } 
    if (condition) 
     MethodB(); 
} 

Чтобы ответить на ваш конкретный вопрос, и этот код, и ваш исходный код будут выполнять MethodB, даже если что-то еще приобретает блокировку.

+0

Это отличный ответ, поэтому спасибо за помощь! – SimpleOne

Смежные вопросы