【问题标题】:Is there a deadlock in following situation and what could be the solution to prevent it?在以下情况下是否存在死锁,有什么解决方案可以防止它?
【发布时间】:2020-09-20 17:00:27
【问题描述】:

我有一个FileLogger 类,它将消息记录到一个txt 文件。我的目的是使FileLogger 类线程安全,以便多个线程可以以线程安全的方式写入日志消息。我有一个锁对象,一次只允许一个线程写入。

同样在同一个应用程序中,我有一个GlobalExceptionHandler 类,它处理所有预期和意外的异常。异常的处理就是记录在一个文件中。所以,GlobalExceptionHandler 最终会调用FileLogger Log 方法来登录到文件。在代码方面可以显示为:

class FileLogger {

  ...

  public void Log(string logOrigin, string message, LogLevel logLevel) {
    //some code
    lock (logWriteLock) {
        try {
          using (var logFileStream = File.Open(logFilePath, FileMode.Append, FileAccess.Write, FileShare.Read)) {
            logFileStream.Write(messageBytes, 0, messageBytes.Length);
            logFileStream.Flush();
          }
        } catch (Exception ex) { 
          globalExceptionHandler.HandleException(ex);
        }
      }
  }

}

class GlobalExceptionHandler {

  public void HandleException(Exception ex) {
    //some code
    fileLogger.Log(...);
  }
}

我的理解:

logWriteLock被线程获取,然后尝试打开文件并写入。快乐的场景会很好,但如果在尝试写入时出现异常,则控件将转到HandleException 方法,该方法将由同一线程执行。HandleException 将再次调用Log。由于线程已经拥有锁,它可以重新进入然后重新尝试写入文件。这将继续下去。

我的理解正确吗?还是会在我们到达globalExceptionHandler.HandleException(ex) 行时立即释放锁(因为我们已经到达临界区的末尾并且方法HandleException 没有显式锁定logWriteLock)?

我有一种直觉,我有循环引用并且会发生死锁。

此外,如果出现死锁,那么可能的解决方案是什么。我们是否需要一个额外的文件来记录 FileLogger 中的异常(我认为这不是一个好主意,因为我们会导致不必要的设计复杂性)?

【问题讨论】:

  • 这里的术语有些偏离,但你的“直觉”是对的。您可能会陷入“无限”循环。您可以做的是通过 globalExceptionHandler 处理这个特定的异常not。但我建议你宁愿做的不是重新发明轮子。使用日志框架。
  • @Fildor 是的,我完全同意不重新发明轮子,但我受到限制,不能使用。此外,不通过 globalExceptionHandler 处理这一特定异常也无法达到将异常处理集中在一个位置的目的。
  • 你不能同时拥有 :( 让全局处理程序处理它绝对是no有意义的。
  • Log 方法不应该做的是抛出异常,或者长时间阻塞调用者。您当前的方法似乎注定要两者兼得!

标签: c# multithreading logging thread-safety locking


【解决方案1】:

或者是不是一打线就释放锁 globalExceptionHandler.HandleException(ex) (因为我们已经走到了尽头 临界区和方法 HandleException 没有明确 锁定 logWriteLock)?

您仍在锁定部分中,从锁定部分调用方法时进入的深度无关紧要。

因此,您将在持有锁的同时永远在里面循环。

当日志记录失败时,没有理由尝试记录异常,因为它也可能会失败。因此,要么使用另一种记录器,要么发送通知,以便在发生此类问题时做出反应。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 2015-11-16
    • 1970-01-01
    • 2020-09-07
    相关资源
    最近更新 更多