8

这不是矫枉过正,而且只有其中之一是必要的吗?我在此处此处搜索并找到了有关 C# 中的互斥和锁定的不同帖子。

示例:
在我们的应用程序中,我们有一个分离多个重新连接线程的函数,在这个线程中我们使用 aMutex和 a lock。不会lock阻止对这部分代码的访问并防止connect被任何其他线程更新吗?

bool connect = false;
Mutex reconnectMutex = new Mutex(false, "Reconnect_" + key);

try
{
   lock(site)
   {
      if(site.ContainsKey(key))
      {
         siteInfo = (SiteInfo)site[key];
         if(reconnectMutex.WaitOne(100, true))
         {
            connect = true;
         }
      }
   }

   if (connect)
   { 
      // Process thread logic
   }
}
catch
{}

reconnectMutex.ReleaseMutex();

更多信息:
这是在 ASP.NET WebService 中,不在 Web Garden 中运行。

4

4 回答 4

11

该 Mutex(因为它有一个名称)也会停止同一台机器上访问它的任何进程,而 lock 只会停止同一进程中的其他线程。从那个代码示例中我看不出为什么你需要两种锁。将简单的锁保持一小段时间似乎是一种好习惯——但随后更重的进程间互斥锁可能会被锁定更长的时间(尽管重叠)!只使用互斥锁会更简单。也许是为了找出进程间锁是否真的有必要。

顺便说一句,catch {}在那种情况下使用绝对是错误的。你应该使用finally { /* release mutex */ }. 它们非常不同。catch 将吞下比它应该的更多种类的异常,并且还将导致嵌套的 finally 处理程序执行以响应低级异常,例如内存损坏、访问冲突等。所以而不是:

try
{
    // something
}
catch
{}

// cleanup

你应该有:

try
{
    // something
}
finally
{
    // cleanup
}

如果您可以从中恢复特定的异常,您可以捕获它们:

try
{
    // something
}
catch (DatabaseConfigurationError x)
{
    // tell the user to configure the database properly
}
finally
{
    // cleanup
}
于 2009-03-13T15:17:05.797 回答
3

"lock" 基本上只是 Montor.Enter/Exit 的语法糖。互斥锁是一种多进程锁。

他们有非常不同的行为。在同一个应用程序或方法中使用两者并没有错,因为它们旨在阻止不同的事物。

但是,就您而言,我认为您最好研究一下信号量和监视器。听起来您不需要跨进程锁定,因此在这种情况下它们可能是更好的选择。

于 2009-03-13T15:21:14.803 回答
2

正如其他人指出的那样,互斥锁跨进程锁定,本地锁(监视器)仅锁定当前进程拥有的那些线程。然而 ...

您显示的代码有一个非常严重的错误。看起来您在最后(即)无条件地释放了 Mutex ,但只有在返回时reconnectMutex.ReleaseMutex()才会获取 Mutex 。site.ContainsKey()true

因此,如果site.ContainsKey返回false,则释放互斥锁将抛出ApplicationException,因为调用线程不拥有互斥锁。

于 2009-03-13T19:12:45.277 回答
1

您没有提供足够的信息来真正回答这个问题。正如 Earwicker 所述,Mutex 允许您跨进程进行同步。因此,如果您运行同一应用程序的两个实例,则可以序列化访问。例如,您可以在使用外部资源时这样做。

现在,您锁定站点可保护站点免受同一进程中其他线程的访问。这可能是必要的,具体取决于其他方法/线程正在做什么。现在,如果这是该站点被锁定的唯一地方,那么是的,我认为这是矫枉过正。

于 2009-03-13T15:22:55.750 回答