2010-11-03 52 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执行。

我需要执行MethodB()因为我不能等待MethodB释放MethodA之前完成之前释放MethodA。另外,我无法在新线程中启动MethodB

+0

如果发生异常锁永远不会被释放,只能在'try .. finally'中使用它 – Andrey 2010-11-03 16:37:06

回答

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 2010-11-03 18:02:13

+1

在原始代码中,该锁专门用于someCondition的评估,而此代码将在锁之外进行评估。如果条件为false,这种双重检查方法可避免输入锁,但如果条件为false,则原始代码实际上在锁的范围内做了某些操作。最后,由于在someCondition的第一次评估中缺乏记忆障碍,“双重检查”方法也很容易出现罕见的种族故障。锁定隐式强加内存屏障。 – 2010-11-03 18:26:05

+0

丹是对的。除了它与原来的行为不同之外,它还有一个微妙的记忆障碍问题。 – 2010-11-03 18:51:05

8

撇开使用“这个”作为一个锁(不好的做法,因为它公开曝光锁定)的问题,这种形式是更清洁和更安全(版本中,如果异常被抛出锁):

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

要回答您的具体问题,即使其他内容获取了锁,此代码和原始代码也会执行MethodB。

+0

这也是一个很好的答案,所以感谢您的帮助! – SimpleOne 2010-11-03 18:12:00